Wxpython 可以在TextCtrl上绘图吗?如果是,怎么做?

Wxpython 可以在TextCtrl上绘图吗?如果是,怎么做?,wxpython,wxwidgets,wxtextctrl,wxperl,Wxpython,Wxwidgets,Wxtextctrl,Wxperl,我正试图用一些线条图来制作一个TextCtrl:简单的东西,我想画在文本上,在它旁边,在线条之间,等等。我在Wx中画画,就像我以前在WxPanels上做的那样:用DCs:$dc->DrawLine(15,15,120,120);等等 到目前为止,我正在这样做:在从TextCtrl派生的类中,我捕获EVT_PAINT并实现我自己的OnPaint函数: sub new { my $class = shift; my $parent = shift; my $self

我正试图用一些线条图来制作一个TextCtrl:简单的东西,我想画在文本上,在它旁边,在线条之间,等等。我在Wx中画画,就像我以前在WxPanels上做的那样:用DCs:$dc->DrawLine(15,15,120,120);等等

到目前为止,我正在这样做:在从TextCtrl派生的类中,我捕获EVT_PAINT并实现我自己的OnPaint函数:

sub new {
     my $class  = shift;
     my $parent = shift;

     my $self = $class->SUPER::new( $parent, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

     EVT_PAINT($self, \&OnPaint );

     return $self;
}

sub OnPaint {
    print"OnPaint: @_ \n";

    # @ravenspoint: this is there I would call the base's paint method
    # first, right? But how??

    my $linesCnt = $_[0]->GetNumberOfLines();

        my $dc = Wx::PaintDC->new($_[0]);
        $dc->DrawLine(
            15, 15,
            120, 120
        );

    # commented out as the base class' paint method will follow,
    # erasing what we've just drawn
    #   $_[1]->Skip(1);
};
现在,问题是:当我让绘制事件向上传播或不向上传播时,控件中的线条或文本被绘制。 对于任何Wx大师来说,这可能是显而易见的,但对我来说,不是。据我所知,TextCtrl是WxWindow的集合体,是一种将文本绘制到其中的低级方法,上面有一个dc和DrawText()以及一些方便的函数,用于设置插入符号等

这种理解对我来说意味着:为了能够画画,我需要访问已经准备好/绘制好的dc,以便我可以继续绘制。对吗?一般来说,在WxPerl中,这是可能的吗?在上面的函数中,我在控件绘制文本之前进行绘制,我认为这是取消注释Skip()时线条消失的原因,因为控件随后会清除并重新绘制dc

有没有办法在TextCtrl完成所有绘图后进入循环

p.S.

在大多数平台上,纯文本Ctrl似乎是通过调用本机文本条目来实现的,尽管文档中没有提到这一点

我在Kephra和Padre中翻找,这两个地方都有一个“右边距指示器”,一条通常为灰色的细线,画在文本区域上。他们是怎么做到的?令人惊讶的是:它们的子类是Wx::闪烁体或旧的Wx::StyledTextCtrl,这两个类都提供了SetEdgeColumn()方法来触发它

问问自己,重新实现我自己的文本小部件是否是将文本绘制到DC上的唯一方法。(难以置信地摇头)


修补*EVT_ERASE_BACKGROUND*和RichtTextCtrl的PaintBackground()没有成功(好吧,在几分钟的黑客攻击之后)。

在覆盖基类paint方法的函数中,在自己的代码之前调用基类paint方法

对于它的价值,这里是如何使用C++

wxTextCtrl::OnPaint()

这不是您想要听到的答案,但您不能使用本机控件(而
wxtxtctrl
就是这样一个)。它已经绘制了自己,您不能干扰它的绘制逻辑,特别是考虑到它在不同平台下是不同的。因此,虽然你有时可以让它工作(特别是在MSW环境下,在MSW环境下,一切皆有可能,也就是说,你可以完全自由地以多种方式射击自己的脚),但这并不能保证在所有平台下都能工作,你真的不应该这样做


如果您想要一些
wxtxtctrl
没有提供的高级功能,您可能应该改为查看
wxRichTextCtrl
。它也完全在wxWidgets本身中实现,即它不是本机的,因此您可以利用它。

我正试图按照VZ的建议行事。下面是一个用于创建RichTextCtrl并在其上画一条线的最小程序。相反,它只绘制一个RichTextCtrl框。如果我注释掉以“self.rtc=”开头的行,它将只绘制该行,而不是RichTextContrl

# sources:
  # http://wiki.wxpython.org/VerySimpleDrawing
  # https://github.com/wxWidgets/wxPython/blob/master/demo/RichTextCtrl.py

import wx
import wx.richtext as rt

class DrawPanel(wx.Frame):
    def __init__(self, *args, **kw):
        wx.Frame.__init__(self, *args, **kw)
        self.rtc = rt.RichTextCtrl(self,style=wx.VSCROLL|wx.HSCROLL|wx.NO_BORDER)
        self.Bind(wx.EVT_PAINT, self.OnPaint)

    def OnPaint(self, event=None):
        dc = wx.PaintDC(self)
        dc.Clear()
        dc.SetPen(wx.Pen(wx.BLACK, 2))
        dc.DrawLine(0, 0, 50, 50)

app = wx.App(False)
frame = DrawPanel(None)
frame.Show()
app.MainLoop()

啊,好的。但我不知道如何在WxPerl中实现这一点。有什么提示吗?调用$self->SUPER::OnPaint()无效。另外:Wx是否会跟踪基地的油漆已经被调用的事实?但除此之外,我似乎只能访问基类'new()…,而不能访问绘画内容。。正确的?(可能是在愚弄我…)对不起,我对wxPerl一无所知。它看起来像一种疯狂的语言!一本好的perl教科书应该告诉你如何在基类中调用一个方法。好吧,除了$self->SUPER::OnPaint()(SUPER是“基类”的Perlish缩写),我也尝试过
Wx::TextCtrl::OnPaint()
,但这似乎没有什么作用,没有抛出错误,但也没有效果。有趣的是在子类化TextCtrl和RichtTextCtrl之间切换(对于后者,我得到了一行,但没有显示文本,而对于TextCtrl,则相反)。我有一种预感,WxPerl对Wx的“某种绑定”在OnPaint中是不完整的…
WxtxtCtrl::OnPaint()
不是wxWidgets API的文档部分(实际上并不存在),永远不应该被显式调用。要让基类进行处理,只需在事件处理程序中调用
event.Skip()
。使用Skip(),我一直有一种关联,它就像调用return()-它会立即退出该子例程。事实并非如此,但是,在OnPaint例程的早期调用Skip(),然后在DC上进行绘制并没有任何效果。大多数wxWidgets控件都是本机控件,没有本机控件的控件可以在未来版本的库和/或底层工具包中使用本机支持重新实现(这种情况在wxGTK中经常发生)。到目前为止,这里没有提到,但TextCtrl可能是通过利用本机小部件实现的,这是另一种可能性。但文档对此保持沉默。因此,为确认TextCtrl是本机控件而竖起大拇指。尽管我也没有幸使用RichTextCtrl。。。