代码之家  ›  专栏  ›  技术社区  ›  kadd11

使用QPaint在QWidgets之间画一条线

  •  4
  • kadd11  · 技术社区  · 7 年前

    我正在开发一个应用程序,在这个应用程序中,我需要能够在两者之间划清界限 QWidget 认为 是在正确的方向,我只是觉得我遗漏了一些东西)是有包含小部件(我称之为 DrawWidget QGridLayout 那就是 QWidget paintEvent 方法并调用 QPainter::drawLine() 作用

    1. 每当我试图画第二条线时,我画的第一条线就会被抹掉。

    这是 包含小部件的功能:

    void paintEvent(QPaintEvent *)
    {
        if (!drewSinceUpdate){
            drewSinceUpdate = true;
            QPainter painter(this);
            painter.setPen(QPen(Qt::black));
    
            painter.drawLine(start->geometry().center(), end->geometry().center());
        }
    }
    

    我尝试了许多不同的方法来获得窗口小部件在最后一行中的正确位置 ,我将发布其中一些方法(我记不清所有方法):

    painter.drawLine(start->pos(), end->pos());
    painter.drawLine(start->mapToGlobal(start->geometry().center()), end->mapToGlobal(end->geometry().center()));
    painter.drawLine(this->mapToGlobal(start->geometry().center()), this->mapToGlobal(end->geometry().center()));
    painter.drawLine(start->mapTo(this, start->pos()), end->mapTo(this, end->pos()));
    painter.drawLine(this->mapFrom(start, start->pos()), this->mapFrom(end, end->pos()));
    

    为了澄清我的问题,这里有一个我想要的例子,摘自 QT Diagram Scene Example Example of what I want 但我最终得到的是:

    What I get 谢谢你能提供的任何帮助。

    注:

    - start end 两者都是 QWidget

    -与相关的层次结构

    QMainWindow
    ->QScrollArea
      ->DrawWidget
        ->QGridLayout
          ->Items       <-- These are the things I want to connect
    

    编辑:为了制作一个完整且可验证的示例,下面是相关代码的全部内容。

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QHBoxLayout>
    #include <QVBoxLayout>
    #include <QTextEdit>
    #include <QPushButton>
    #include <QScrollBar>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        // Setting up the relevant hierarchy 
        ui->setupUi(this);
        scrollArea = new QScrollArea();
        setCentralWidget(scrollArea);
    
        drawWidget = new DrawWidget();
        gridLayout = new QGridLayout();
        gridLayout->setSpacing(300);
        drawWidget->setLayout(gridLayout);
    
        scrollArea->setWidget(drawWidget);
        scrollArea->setWidgetResizable(true);
    
        AddItemSlot();
    
        QApplication::connect(scrollArea->horizontalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(scrollHorizontal()));
    }
    
    // This is just creating a single one of the example widgets which I want to connect
    QWidget* MainWindow::CreateNewItem(){
        QWidget* itemWidget = new QWidget();
        itemWidget->setStyleSheet("background-color: lightgray");
        QHBoxLayout* singleItemLayout = new QHBoxLayout();
        itemWidget->setLayout(singleItemLayout);
    
        QTextEdit* textEdit = new QTextEdit(std::to_string(counter++).c_str());
        textEdit->setStyleSheet("background-color:white;");
        singleItemLayout->addWidget(textEdit);
    
        QVBoxLayout* rightSidePanel = new QVBoxLayout();
        rightSidePanel->setAlignment(Qt::AlignTop);
    
        QPushButton* button1 = new QPushButton("Top Button");
    
        QApplication::connect(button1, SIGNAL(clicked(bool)), this, SLOT(AddItemSlot()));
    
        rightSidePanel->addWidget(button1);
    
        QWidget* rightPanelWidget = new QWidget();
        rightSidePanel->setMargin(0);
        rightPanelWidget->setLayout(rightSidePanel);
    
        singleItemLayout->addWidget(rightPanelWidget);
    
        itemWidget->setLayout(singleItemLayout);
        itemWidget->setMinimumWidth(400);
        itemWidget->setFixedSize(400,200);
    
        return itemWidget;
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::scrollHorizontal()
    {
        scrollArea->ensureWidgetVisible(noteItems.back());
    }
    
    void MainWindow::AddItemSlot()
    {
        QWidget* w = CreateNewItem();
        gridLayout->addWidget(w,currRow, currCol++);
        if (!noteItems.empty()){
            drawWidget->updateEndpoints(noteItems.back(), w);
        }
        noteItems.push_back(w);
    }
    

    主窗口.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QGridLayout>
    #include <QWidget>
    #include <QMainWindow>
    #include <QScrollArea>
    #include <drawwidget.h>
    #include "drawscrollarea.h"
    #include <vector>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    public slots:
        void scrollHorizontal();
        void AddItemSlot();
    
    private:
        Ui::MainWindow *ui;
        QWidget* CreateNewItem();
        int counter = 0, currCol = 0, currRow = 0;
        std::vector<QWidget*> noteItems;
    
        QScrollArea* scrollArea;
        DrawWidget* drawWidget;
        QGridLayout* gridLayout;
    };
    
    #endif // MAINWINDOW_H
    

    #include "drawwidget.h"
    #include <QDebug>
    #include <QRect>
    
    DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    void DrawWidget::paintEvent(QPaintEvent *)
    {
        if (!drewSinceUpdate){
            drewSinceUpdate = true;
            QPainter painter(this);
            painter.setPen(QPen(Qt::black));
    
            for (ConnectedPair pair : items){
                const QWidget* from = pair.from;
                const QWidget* to =pair.to;
    
                QPoint start =  from->mapToGlobal(from->rect().topRight() +  QPoint(0, from->height()/2));
                QPoint end = to->mapToGlobal(to->rect().topLeft() +  QPoint(0, to->height()/2));
    
                painter.drawLine(mapFromGlobal(start), mapFromGlobal(end));
            }
        }
    }
    
    void DrawWidget::updateEndpoints(QWidget* startIn, QWidget* endIn){
        drewSinceUpdate = false;
        items.push_back(ConnectedPair{startIn, endIn});
    }
    

    DrawWidget.h

    #ifndef DRAWWIDGET_H
    #define DRAWWIDGET_H
    
    #include <QWidget>
    #include <QPainter>
    #include <QtCore>
    #include <vector>
    
    class DrawWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit DrawWidget(QWidget *parent = nullptr);
        void updateEndpoints(QWidget* startIn, QWidget* endIn);
        virtual void paintEvent(QPaintEvent *);
    signals:
    
    private:
        struct ConnectedPair {
            const QWidget* from;
            const QWidget* to;
        };
    
        std::vector<ConnectedPair> items;
        bool drewSinceUpdate = true;
    };
    
    #endif // DRAWWIDGET_H
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   eyllanesc Yonghwan Shin    4 年前

    在这种情况下,我们使用函数 mapToGlobal() mapfromGlobal()

    drawwidget.h

    #ifndef DRAWWIDGET_H
    #define DRAWWIDGET_H
    
    #include <QWidget>
    
    class DrawWidget : public QWidget
    {
        Q_OBJECT
    public:
        explicit DrawWidget(QWidget *parent = nullptr);
    
        void addWidgets(const QWidget *from, const QWidget *to);
    
    protected:
        void paintEvent(QPaintEvent *);
    
    private:
        struct WidgetsConnected {
            const QWidget* from;
            const QWidget* to;
        };
    
        QList<WidgetsConnected> list;
    
    };
    
    #endif // DRAWWIDGET_H
    

    #include "drawwidget.h"
    
    #include <QPainter>
    DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
    {
    }
    
    void DrawWidget::addWidgets(const QWidget * from, const QWidget * to)
    {
        list.append(WidgetsConnected{from , to});
        update();
    }
    
    void DrawWidget::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        for(const WidgetsConnected el: list){
            const QWidget* from = el.from;
            const QWidget* to = el.to;
    
            QPoint start =  from->mapToGlobal(from->rect().topRight() +  QPoint(0, from->height()/2));
            QPoint end = to->mapToGlobal(to->rect().topLeft() +  QPoint(0, to->height()/2));
    
            painter.drawLine(mapFromGlobal(start), mapFromGlobal(end));
        }
    }
    

    可以找到完整的示例 here

    enter image description here