none
Graphics.DrawString() 文字表示不可 RRS feed

  • 質問

  • お世話になっております。

    [TabControl]のページに複数の[Panel]を配置し、その上に[Label][Button][TextBox]等を配置した。
    パネル単位でクラスを作成し、表示等OKである。

    今回、その一部のクラスをやめて、フォーム単位での[partial]クラスにしてそれぞれはメソッドにしてみた。
    ところがこの場合ですと、Graphics.DrawString() でする文字表示のみ表示出来ないのです。

    以下、プログラムの要約です。


    namespace   namespace1
    {
        public partial class    form1 : Form
        {
             private void    tabControl1_SelectedIndexChanged(
            {
                switch (tabControl1.SelectedIndex)    // タブコントロールのページ選択
                case page1:
                    subProgram1(tab1);                       // メソッドをコール    >>>>>>

                    c1 = new classProgram2(tab1);     // クラスをインスタンス


    namespace   namespace1
    {
        public    partial class    form1 : Form        // 部分クラス:フォーム
        {
              public     void    subProgram1(Control parent)    // メソッド
            {
                Control    this.parent = parent;

                Panel    pnl = new Panel();                      // パネル
                pnl. 各プロパティ設定
                parent.Controls.Add(pnl);                        // タブコントロール上のパネル

                 Graphics    g = pnl.CreateGraphics();      // パネル上のg    <<<<<
                 g.DrawString("xxx", ---                            // 表示NG     <<<<<
             // Graphics    g = parent.CreateGraphics(); // タブコントロール上のg
             // g.DrawString("xxx", ---                            // 表示OK

                --- 中略 ---
                pnl.Controls.Add(lbl[i]);
                lbl[i].Text = 999;                                      // 表示OK


    namespace   namespace1
    {
        public    class    classProgram2                       // クラス
        {
            public    classProgram1(Control parent)
            {
                Control    this.parent = parent;

                Panel    pnl = new Panel();                   // パネル
                pnl. 各プロパティ設定
                parent.Controls.Add(pnl);                     // タブコントロール上のパネル

                Graphics    g = pnl.CreateGraphics();    // パネル上のg
                g.DrawString(" xxx ", ---                        // 表示OK

    御手数をお掛けしますが、よろしくご教授お願いします。

    2010年8月6日 3:49

回答

  • 通常、描画操作は、表示が必要な際に呼び出される Paint イベントを利用して行います。
    CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。
    再表示がすぐに発生するか、なかなか発生しないかは状況によって様々ですので、OKの方も大丈夫とはいえません。

    追記:ご質問内容には関係ないですが、
    CreateGraphics で作ったインスタンスは、using などを利用して必ずリソースを解放する必要があります。

    さらに追記:Paint イベントを利用する場合は、CreateGraphics は使用せずに、e.Graphics に対して描画を行います。

    • 編集済み TH01 2010年8月6日 5:07 さらに追記
    • 回答としてマーク 黄昏男子 2010年8月7日 0:55
    2010年8月6日 4:56
  • > CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。

    これは知りませんでした。試すと確かに消えてしまいますね。まだまだ修行不足です。orz

    よって勉強のためコード、TH01 さんの指摘を考慮にいれつつ書いてみました。 こんな感じになりますね。

    Panel _pnl = null;
    
    /// 
    /// パネルを追加
    /// 
    public void AddPanel(TabPage parent) {
     Panel pnl = new Panel();
     pnl.Dock = DockStyle.Fill;
     pnl.BackColor = Color.White;
     pnl.Paint += panel1_Paint;
     parent.Controls.Add(pnl);
     pnl.Show();
     _pnl = pnl;
    }
    
    /// 
    /// 文字列をパネルに描画
    /// 
    private void DrawString(Graphics graphic) {
    
     if (_pnl == null) return;
    
     string drawString = "Sample Text";
     Font drawFont = new Font("Arial", 16);
     SolidBrush drawBrush = new SolidBrush(Color.Black);
    
     // 解放は不要
     graphic.DrawString(drawString, drawFont, drawBrush, 10, 10);
    }
    
    /// 
    /// タブページ変更時のイベントハンドラ
    /// 
    private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
    
     this.AddPanel(tabControl1.TabPages[tabControl1.SelectedIndex]);
    }
    
    /// 
    /// 追加したパネルの描画イベントハンドラ
    /// 
    private void panel1_Paint(object sender, PaintEventArgs e) {
     this.DrawString(e.Graphics);
    }
    
    

    ひらぽん http://d.hatena.ne.jp/hilapon/
    • 回答としてマーク 黄昏男子 2010年8月7日 0:55
    2010年8月6日 6:54
    モデレータ

すべての返信

  • namespace   namespace1
    {
        public    partial class    form1 : Form        // 部分クラス:フォーム
        {
              public     void    subProgram1(Control parent)    // メソッド
            {
                Control    this.parent = parent;

                Panel    pnl = new Panel();                      // パネル
                pnl. 各プロパティ設定
                parent.Controls.Add(pnl);                        // タブコントロール上のパネル

                Graphics    g = pnl.CreateGraphics();       // パネル上のg    <<<<<
                g.DrawString("xxx", ---                           // 表示NG     <<<<<

    上記見てて思ったのですが、

    Control this.parent = parent;

    この一行、おかしくないですか?この一行削ればうまくいくように思えますが・・・


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2010年8月6日 4:22
    モデレータ
  • 通常、描画操作は、表示が必要な際に呼び出される Paint イベントを利用して行います。
    CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。
    再表示がすぐに発生するか、なかなか発生しないかは状況によって様々ですので、OKの方も大丈夫とはいえません。

    追記:ご質問内容には関係ないですが、
    CreateGraphics で作ったインスタンスは、using などを利用して必ずリソースを解放する必要があります。

    さらに追記:Paint イベントを利用する場合は、CreateGraphics は使用せずに、e.Graphics に対して描画を行います。

    • 編集済み TH01 2010年8月6日 5:07 さらに追記
    • 回答としてマーク 黄昏男子 2010年8月7日 0:55
    2010年8月6日 4:56
  • > CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。

    これは知りませんでした。試すと確かに消えてしまいますね。まだまだ修行不足です。orz

    よって勉強のためコード、TH01 さんの指摘を考慮にいれつつ書いてみました。 こんな感じになりますね。

    Panel _pnl = null;
    
    /// 
    /// パネルを追加
    /// 
    public void AddPanel(TabPage parent) {
     Panel pnl = new Panel();
     pnl.Dock = DockStyle.Fill;
     pnl.BackColor = Color.White;
     pnl.Paint += panel1_Paint;
     parent.Controls.Add(pnl);
     pnl.Show();
     _pnl = pnl;
    }
    
    /// 
    /// 文字列をパネルに描画
    /// 
    private void DrawString(Graphics graphic) {
    
     if (_pnl == null) return;
    
     string drawString = "Sample Text";
     Font drawFont = new Font("Arial", 16);
     SolidBrush drawBrush = new SolidBrush(Color.Black);
    
     // 解放は不要
     graphic.DrawString(drawString, drawFont, drawBrush, 10, 10);
    }
    
    /// 
    /// タブページ変更時のイベントハンドラ
    /// 
    private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
    
     this.AddPanel(tabControl1.TabPages[tabControl1.SelectedIndex]);
    }
    
    /// 
    /// 追加したパネルの描画イベントハンドラ
    /// 
    private void panel1_Paint(object sender, PaintEventArgs e) {
     this.DrawString(e.Graphics);
    }
    
    

    ひらぽん http://d.hatena.ne.jp/hilapon/
    • 回答としてマーク 黄昏男子 2010年8月7日 0:55
    2010年8月6日 6:54
    モデレータ
  • ひらぽん様、

    TH01様

    有難うございます。 m(_^_)m

     

    「Paint イベント」で描画しないと再表示で消えてしまいます、ということは前々回の御指摘で承知して、そのように構成していたのですが

    (プログラムの要約は、行数を減らすためにその部分はカットしてしまった)、

    paintイベントの中で[CreateGraphics]を依然として使っていました。

    「CreateGraphics は使用せずに、e.Graphics に対して描画」に改版したところ、上手く描画できました。

     

    御回答を印刷して勉強させて貰いました。

    御両所様のお陰で、とても助かりました。

    もっと精進して頑張りたいと思います。

    2010年8月7日 0:55