トップ回答者
Graphics.DrawString() 文字表示不可

質問
-
お世話になっております。
[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
御手数をお掛けしますが、よろしくご教授お願いします。
回答
-
通常、描画操作は、表示が必要な際に呼び出される Paint イベントを利用して行います。
CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。
再表示がすぐに発生するか、なかなか発生しないかは状況によって様々ですので、OKの方も大丈夫とはいえません。
追記:ご質問内容には関係ないですが、
CreateGraphics で作ったインスタンスは、using などを利用して必ずリソースを解放する必要があります。
さらに追記:Paint イベントを利用する場合は、CreateGraphics は使用せずに、e.Graphics に対して描画を行います。 -
> 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
すべての返信
-
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/ -
通常、描画操作は、表示が必要な際に呼び出される Paint イベントを利用して行います。
CreateGraphics を使って描画を行っても、次回の再表示によって消えてしまいます。
再表示がすぐに発生するか、なかなか発生しないかは状況によって様々ですので、OKの方も大丈夫とはいえません。
追記:ご質問内容には関係ないですが、
CreateGraphics で作ったインスタンスは、using などを利用して必ずリソースを解放する必要があります。
さらに追記:Paint イベントを利用する場合は、CreateGraphics は使用せずに、e.Graphics に対して描画を行います。 -
> 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
-
ひらぽん様、
TH01様
有難うございます。 m(_^_)m
「Paint イベント」で描画しないと再表示で消えてしまいます、ということは前々回の御指摘で承知して、そのように構成していたのですが
(プログラムの要約は、行数を減らすためにその部分はカットしてしまった)、
paintイベントの中で[CreateGraphics]を依然として使っていました。
「CreateGraphics は使用せずに、e.Graphics に対して描画」に改版したところ、上手く描画できました。
御回答を印刷して勉強させて貰いました。
御両所様のお陰で、とても助かりました。
もっと精進して頑張りたいと思います。