事件处理程序和重写OnPaint方法 [英] Event Handler and overriding OnPaint method

查看:96
本文介绍了事件处理程序和重写OnPaint方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好。我需要通过重写OnPaint()方法在c#中绘制一个面板。问题是我有一个类表,它接收列数和行数的2个值。基于列和行的数量,我需要永远使用OnPaint()方法在具有该列数和行数的面板上绘制。



class Table witch接收列数和行数并覆盖OnPaint方法是:

Hello. I need to paint a panel in c# by overriding OnPaint() method. The problem is that i have a class table which receive 2 values of number of column and rows. Based on number of columns and rows i need to everride OnPaint() method to draw on a form that a panel with that numbers of column and rows.

class Table witch receive number of columns and rows and override OnPaint method is:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Drawing;
using System.Windows.Forms;

namespace Airplanes
{
    public class Table: Panel
    {
        private int columns;
        private int rows;

        public int Columns 
        {
            get 
            { 
                return columns; 
            } 
            private set 
            { 
                columns = value; 
            } 
        }
        public int Rows 
        { 
            get 
            { 
                return rows; 
            } 
            private set 
            { 
                rows = value; 
            } 
        }

        public Table()
        {
            Coordonates c = new Coordonates();
            var coordonates = c.ObtainTableSize();
            columns = coordonates[0];
            rows = coordonates[1];
        }

        //public event PaintEventHandler paint;
        //public PaintEventArgs e = null;
        //public delegate void PaintEventHandler(Table table, PaintEventArgs e);

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            System.Drawing.Pen myPen = new System.Drawing.Pen(Color.Black);

            for (int i = 0; i < rows; i++)
            {
                e.Graphics.DrawLine(myPen, new Point(10, 10 + (i * 5)), new Point(100, 10 + (i * 5)));
            }
        }
    }
}





这是Form class我在哪里需要调用onPaint方法并绘制面板:



And this is Form class where i need to call the onPaint method and draw the panel:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Airplanes
{
    public partial class GameForm : Form
    {
        Panel panel;
        Table tb = new Table();

        public GameForm()
        {
            InitializeComponent();

            panel = new Panel();
            panel.Visible = true;
            panel.Location = new Point(200, 40);
            panel.Size = new Size(tb.Columns*100, tb.Rows*100);
            panel.BackColor = Color.AliceBlue;
           
        }

        //public void SubscribeToEvent(Table sender)
        //{
        //    sender.paint += new Table.PaintEventHandler(OnPaint);
        //}

        private void GameForm_Load(Table sender, EventArgs e)
        {
            //this.SubscribeToEvent(tb);
            //tb.Start();
            this.Controls.Add();
        }

    }
}





有人可以帮我吗?谢谢!



Anyone can help me please? Thanks!

推荐答案

请参阅我对解决方案1的评论,这不太正确,请不要将其用作指示。



请同时查看我过去的答案:

捕捉面板上的图纸 [ ^ ],

什么样的俏皮方法是Paint? (DataGridViewImageCell.Paint(...)) [ ^ ],

mdi子表单之间的绘制线 [ ^ ],

如何加速我的vb.net应用程序? [ ^ ],

用C#.net鼠标滚轮缩放图像 [ ^ ]。



看起来你的问题是将参数传递给渲染方法(它不能接受其他参数,只接受事件参数)。这里的关键是:这是实例方法,即不是静态方法。这意味着,它可以通过this(隐式)参数访问声明类的实例。实际上,您应该在控件的声明类中显示一些数据模型。此数据应在 OnPaint 方法中使用。每次更改数据时,都需要强制重新渲染。怎么样?正如Ron指出的那样,通过调用 Invalidate 方法中的一个:

http://msdn.microsoft.com/en-us/library/system.windows.forms .control.invalidate%28v = vs.110%29.aspx [ ^ ]。



为防止闪烁,请使用双缓冲 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered(v = vs.110).aspx [ ^ ]。< br $>


-SA
Please see my comments to Solution 1, which is not quite correct, please don't use it as directions.

Please also see my past answers:
capture the drawing on a panel[^],
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
Drawing Lines between mdi child forms[^],
How to speed up my vb.net application?[^],
Zoom image in C# .net mouse wheel[^].

It looks like you problem is to pass parameter to the rendering method (which cannot accept other parameters, only event arguments). The key here is: this is the instance method, that is, not a static method. It means, it has the access to the instance of declaring class via the "this" (implicit) parameter. In practice, you should have some data model visible in the control's declaring class. This data should be used in your OnPaint method. Each time you change the data, you need to force re-rendering. How? As Ron pointed it out, via calling (one of) the Invalidate methods:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invalidate%28v=vs.110%29.aspx[^].

For preventing flicker, use double buffering: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered(v=vs.110).aspx[^].

—SA


你唯一遗漏的我可以当您更改表的行或列时,see是对this.Invalidate()的调用。这表示控件要重绘,然后调用你的OnPaint方法。
The only thing you are missing I can see is a call to this.Invalidate() when you change the Rows or Columns of your table. This signals the control to be redrawn, which will then call your OnPaint method.


你好calincoosmin,



看来你好吗我需要帮助编写代码,但要理解WinForms中的owner draw概念。



*如果覆盖OnPaint,则不应调用base.Paint处理程序(你不希望在你的情况下完成默认绘图)。

*尝试通过覆盖OnResize来优化绘画性能并在那里进行所有大小的基础计算,尽量不要创建在油漆过程中对象(钢笔,刷子),但创建它们一次(例如在施工期间)并重复使用它们。

*如果你想在另一个控件或表格上使用你的所有者绘制控件,则不需要特殊的绘图调用(因为你已经编写了Paint-Method来自己处理所有绘画)。只需放置控件,如果你的绘图功能有效,你应该在设计师中看到绘制的控件(并不总是可能)。



为什么你的实际代码没有?为你工作对我来说并不是一件容易的事 - 看了之后它应该按预期工作(不是性能优化,而是工作)



也许一个原因可能就是你正在使用0行和列(?)进行初始化,然后使用0 * 100,0 * 100进行控制?换句话说,你是否可以从ObtainTableSize方法获得有效的表格大小?



亲切的问候Johannes
Hi calincoosmin,

It seems you don't need help with coding but with understanding the "owner draw" concept in WinForms looks like.

* If you override OnPaint you shouldn't call the base.Paint handler(you don't want the default drawing to be done in your case I think).
* Try to optimize painting performance by also overriding OnResize and do all size base calculations there, try to not create objects (Pens, Brushes) during paint but create them once (e.g. during construction) and reuse them.
* If you want to use your "owner drawn" control on another control or form no special drawing call should be needed (cause you have written the Paint-Method to handle all painting for it self). Just place the control, and if your paint function works, you should see the painted control also in the designer (not always possible).

Why your actual code doesn't work for you is not obviouse for me - after a quick look it should work as expected (not perfomance optimized, but working)

Maybe one cause could be if you are initializing with 0 rows and columns(?) and then the control with 0*100, 0*100? In other words are you shure you get a valid table size from ObtainTableSize method?

Kind regards Johannes


这篇关于事件处理程序和重写OnPaint方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆