【问题标题】:draw in a QFrame on clicking a button.单击按钮时在 QFrame 中绘制。
【发布时间】:2023-03-06 05:24:01
【问题描述】:

假设有一个名为“Draw”的 QPushButton、一个 QLineEdit 和一个 QFrame。单击按钮时,我想从 QLineEdit 中获取一个数字并在 QFrame 中绘制一个圆圈。我怎样才能做到这一点?请把代码提供给我。

附:问题是QPainter的draw方法应该在drawEvent方法中调用。

【问题讨论】:

    标签: c++ qt drawing qpainter


    【解决方案1】:

    如果@Kaleb Pederson's answer 对您来说还不够,那么这里有一个完整的解决方案,用于与您描述的内容相匹配的简单设置。在 Linux 上使用 Qt 4.5.2 进行测试。我有一些空闲时间... ;)

    main.cpp:

    #include <QApplication>
    #include "window.h"
    
    int main( int argc, char** argv )
    {
        QApplication qapp( argc, argv );
    
        Window w;
        w.show();
    
        return qapp.exec();
    }
    

    window.h

    #pragma once
    
    class QLineEdit;
    class QPushButton;
    #include <QWidget>
    
    class Frame;
    
    class Window : public QWidget
    {
    Q_OBJECT
    
    public:
        Window();
    
    private slots:
        void onButtonClicked();
    
    private:
        QLineEdit*   m_lineEdit;
        QPushButton* m_pushButton;
        Frame*       m_frame;
    };
    

    window.cpp:

    #include <QHBoxLayout>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QVBoxLayout>
    
    #include "frame.h"
    #include "window.h"
    
    Window::Window()
        : m_lineEdit  ( new QLineEdit( this ) )
        , m_pushButton( new QPushButton( tr( "Draw" ), this ) )
        , m_frame     ( new Frame( this ) )
    {
        connect( m_pushButton, SIGNAL( clicked() )
               , SLOT( onButtonClicked() ) );
    
        QHBoxLayout*const hLayout = new QHBoxLayout;
        hLayout->addWidget( m_lineEdit );
        hLayout->addWidget( m_pushButton );
    
        QVBoxLayout*const vLayout = new QVBoxLayout( this );
        vLayout->addLayout( hLayout );
        m_frame->setFixedSize( 300, 400 );
        vLayout->addWidget( m_frame );
    
        setLayout( vLayout );
    }
    
    void Window::onButtonClicked()
    {
        const int r = m_lineEdit->text().toInt(); // r == 0 if invalid
        m_frame->setCircleRadius( r );
        m_frame->update();
    }
    

    frame.h:

    #pragma once
    
    #include <QFrame>
    
    class Frame : public QFrame
    {
    Q_OBJECT
    
    public:
        Frame( QWidget* );
    
        void setCircleRadius( int );
    
    protected:
        void paintEvent( QPaintEvent* );
    
    private:
        int m_radius;
    };
    

    frame.cpp:

    #include <QPainter>
    
    #include "frame.h"
    
    Frame::Frame( QWidget* parent )
        : QFrame( parent )
        , m_radius( 0 )
    {
        setFrameStyle( QFrame::Box );
    }
    
    void Frame::setCircleRadius( int radius )
    {
        m_radius = radius;
    }
    
    void Frame::paintEvent( QPaintEvent* pe )
    {
        QFrame::paintEvent( pe );
    
        if ( m_radius > 0 )
        {
            QPainter p( this );
            p.drawEllipse( rect().center(), m_radius, m_radius );
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果你想让你的框架进行绘图,那么它需要一种方法来知道它应该绘制一些东西,所以创建一个接收通知的槽:

      /* slot */ void drawCircle(QPoint origin, int radius) {
          addCircle(origin, radius);
          update(); // update the UI
      }
      
      void addCircle(QPoint origin, int radius) {
          circleList.add(new Circle(origin,radius));
      }
      

      然后,您需要覆盖 paintEvent() 来绘制圆圈的框架子类:

      void paintEvent(QPaintEvent *event) {
          QFrame::paintEvent(event);
          QPainter painter(this);
          foreach (Circle c, circleList) { // understand foreach requirements
              painter.drawEllipse(c.origin(), c.radius(), c.radius());
          }
      }
      

      只要响应按钮的clicked() 信号的槽发出一个信号,用正确的参数调用drawCircle 槽,一切都应该正常工作。

      【讨论】:

        【解决方案3】:

        您不会直接在框架上绘图。
        从这里开始graphicsview,一开始看起来很复杂——但是当你第一次遇到它时,GUI程序是一个很大的飞跃

        在大多数 GUI(Qt、OpenGL 等)中,您会建立一个您想要在程序中绘制的元素列表并以某种方式存储它们 - 然后当计算机需要绘制您的图片时会调用一个 draw() 函数- 例如,当它被移动或另一个窗口移动到它前面时。然后调用 OnDraw 或 OnRepaint 等函数,您必须绘制对象列表。

        另一种方法是将它们全部绘制到图像(QOimage 或 QPixmap)并在 OnDraw 或 OnRepaint 中将其复制到屏幕 - 例如,您可以为图形包执行此操作。

        【讨论】:

        • "你不能直接在框架上绘图。"为什么不呢?
        • "QFrame 类是可以有框架的小部件的基类"
        • 您仍然可以直接在QFrame 或其任何子类上绘图。有关工作示例,请参阅 my anwser
        • 我看到 QGraphicsView 和 QGraphicsScene 是我需要的,但我无法在我想要的 QGraphicsScene 中放置文本。该类的 addText() 方法没有指定坐标的参数。我该怎么做?
        • @Martin Beckett:这就是要求证明的。我曾经在一个 Qt 应用程序上工作,该应用程序在 QGraphicsView 存在之前就已经编写好了,我们从不费心移植到它,因为一切都很好。 QGraphicsView 是 GUI 的一个不错的新部分,但我不会说它是强制性的。
        猜你喜欢
        • 2022-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-13
        相关资源
        最近更新 更多