以编程方式创建 QWidgets 时遇到问题

Trouble creating QWidgets programmatically

该程序应该通过从左侧提供的标签之一拖动来在中央区域创建一组 DraggableLabel。一旦它们存在,它们应该能够在单击或长按时四处拖动并执行不同的操作。

基于从 MouseDown 到 MouseUp 的计时器,长按有效,但为清楚起见未包含在此处。

对我做错了什么有什么想法吗?特别是为什么 test() 函数有效,但是当我 copy/paste 它的代码进入我想要的 LabelMouseUp() 时,它却不起作用?

我也愿意接受更好的方法。


Lights.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2015-09-19T12:47:09
#
#-------------------------------------------------

QT      += core gui
CONFIG  += C++11

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Lights
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp \
    draggablelabel.cpp

HEADERS  += mainwindow.h \
    draggablelabel.h

main.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    new MainWindow();
    return app.exec();
}

draggablelabel.h:

#ifndef DRAGGABLELABEL_H
#define DRAGGABLELABEL_H

#include <QLabel>
#include <QMouseEvent>
#include <QEvent>

class DraggableLabel : public QLabel
{
    Q_OBJECT
public:
    explicit DraggableLabel(QWidget *parent = 0);

    void mousePressEvent(QMouseEvent* ev);
    void mouseReleaseEvent(QMouseEvent* ev);
    void mouseMoveEvent(QMouseEvent* ev);

signals:
    void MouseDown(DraggableLabel* sender, int x, int y);
    void MouseUp(DraggableLabel* sender, int x, int y);
    void MouseMove(DraggableLabel* sender, int x, int y);

public slots:

};

#endif // DRAGGABLELABEL_H

draggablelabel.cpp:

#include "draggablelabel.h"

DraggableLabel::DraggableLabel(QWidget *parent) :
    QLabel(parent)
{
}

void DraggableLabel::mousePressEvent(QMouseEvent *ev)
{
    emit MouseDown(this, ev->x(), ev->y());
    ev->accept();
}

void DraggableLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    emit MouseUp(this, ev->x(), ev->y());
    ev->accept();
}

void DraggableLabel::mouseMoveEvent(QMouseEvent *ev)
{
    emit MouseMove(this, ev->x(), ev->y());
    ev->accept();
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtWidgets>
#include "draggablelabel.h"

class ResizeFilter : public QObject
{
    Q_OBJECT

public:
    ResizeFilter();

protected:
    bool eventFilter(QObject* obj, QEvent* event);

signals:
    void ResizeEvent(QSize size);
};



class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    ResizeFilter* filter;

    QPixmap* newPixmap;
    QPixmap* filePixmap;

    QWidget* pageScenes;
    QWidget* panelScenes;
    QWidget* panelSceneButtons;
    DraggableLabel* labelSceneNew;
    DraggableLabel* labelSceneFile;

    int panelwidth;

    QList<DraggableLabel*>* allScenes;

    bool mouseIsDown;

    QPlainTextEdit* debugLabel;

    QString IdentifyFunctionLabel(DraggableLabel* label);

    void test();

private slots:
    void FinishInit(QSize size);

    void LabelMouseDown(DraggableLabel* sender, int x, int y);
    void LabelMouseUp(DraggableLabel* sender, int x, int y);
    void LabelMouseMove(DraggableLabel* sender, int x, int y);
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"

ResizeFilter::ResizeFilter()
    : QObject()
{

}

bool ResizeFilter::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::Resize)
    {
        QResizeEvent* resizeEv = static_cast<QResizeEvent*>(event);
        emit ResizeEvent(resizeEv->size());
    }
    return QObject::eventFilter(obj, event);
}



MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    filter = new ResizeFilter();
    installEventFilter(filter);
    showMaximized();    //do this before connecting so we miss the first resize event (wrong size) and catch the second (right size)
    connect(filter, SIGNAL(ResizeEvent(QSize)),
            this, SLOT(FinishInit(QSize)));
}

void MainWindow::FinishInit(QSize size)
{
    disconnect(filter, SIGNAL(ResizeEvent(QSize)),
               this, SLOT(FinishInit(QSize)));
    delete filter;

    allScenes = new QList<DraggableLabel*>();

    mouseIsDown = false;

    QString filepath = QCoreApplication::applicationDirPath();

    newPixmap = new QPixmap(filepath + "/Icons/New.png");
    filePixmap = new QPixmap(filepath + "/Icons/File.png");

    QWidget* centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);

    pageScenes = new QWidget(centralWidget);
    panelScenes = new QWidget(pageScenes);
    panelScenes->setStyleSheet("background-color: darkgray");
    panelSceneButtons = new QWidget(pageScenes);
    panelSceneButtons->setStyleSheet("background-color: lightgray");
    labelSceneNew = new DraggableLabel(panelSceneButtons);
    labelSceneNew->setStyleSheet("background-color: darkgray");
    labelSceneNew->setPixmap(*newPixmap);
    labelSceneNew->setAlignment(Qt::AlignCenter);
    labelSceneFile = new DraggableLabel(panelSceneButtons);
    labelSceneFile->setStyleSheet("background-color: darkgray");
    labelSceneFile->setPixmap(*filePixmap);
    labelSceneFile->setAlignment(Qt::AlignCenter);

    debugLabel = new QPlainTextEdit(centralWidget);
    debugLabel->setReadOnly(true);
    debugLabel->setStyleSheet("background-color: white");
    debugLabel->setFont(QFont("Courier New", 7));

    int fullwidth = size.width();
    int fullheight = size.height();
        panelwidth = fullwidth/10;
    int buttonborder = 1;
    int buttonsize = panelwidth-(2*buttonborder);

    panelScenes->setGeometry(panelwidth, 0, fullwidth-(2*panelwidth), fullheight);                      //center area for user's canvas
    panelSceneButtons->setGeometry(0, 0, panelwidth, fullheight);                                       //button area on the left side
    labelSceneNew->setGeometry(buttonborder, buttonborder, buttonsize, buttonsize);                     //buttons on the left side
    labelSceneFile->setGeometry(buttonborder, buttonsize+(3*buttonborder), buttonsize, buttonsize);     //buttons on the left side (count borders from top, including one of its own)

    debugLabel->setGeometry(fullwidth-(panelwidth), 0, panelwidth, fullheight);

    connect(labelSceneNew, SIGNAL(MouseDown(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseDown(DraggableLabel*,int,int)));
    connect(labelSceneNew, SIGNAL(MouseUp(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseUp(DraggableLabel*,int,int)));
    connect(labelSceneNew, SIGNAL(MouseMove(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseMove(DraggableLabel*,int,int)));

    connect(labelSceneFile, SIGNAL(MouseDown(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseDown(DraggableLabel*,int,int)));
    connect(labelSceneFile, SIGNAL(MouseUp(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseUp(DraggableLabel*,int,int)));
    connect(labelSceneFile, SIGNAL(MouseMove(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseMove(DraggableLabel*,int,int)));

    test();
}

MainWindow::~MainWindow()
{

}

void MainWindow::test()
{
    DraggableLabel* newlabel = new DraggableLabel(panelScenes);
    newlabel->setStyleSheet("background-color: darkgray");
    newlabel->setPixmap(*newPixmap);
    newlabel->setAlignment(Qt::AlignCenter);
    newlabel->setGeometry(200, 200, 100, 100);  //icons are 96 x 96
    connect(newlabel, SIGNAL(MouseDown(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseDown(DraggableLabel*,int,int)));
    connect(newlabel, SIGNAL(MouseUp(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseUp(DraggableLabel*,int,int)));
    connect(newlabel, SIGNAL(MouseMove(DraggableLabel*,int,int)),
            this, SLOT(LabelMouseMove(DraggableLabel*,int,int)));
    *allScenes << newlabel;
}

QString MainWindow::IdentifyFunctionLabel(DraggableLabel* label)
{
    if(label == labelSceneNew)      return "  SceneNew ";
    if(label == labelSceneFile)     return "  SceneFile";
                                    return "??unknown??";
}

void MainWindow::LabelMouseDown(DraggableLabel* sender, int x, int y)
{
    debugLabel->appendPlainText(QString("%1: Down:%2,%3").arg(IdentifyFunctionLabel(sender)).arg(x).arg(y));

    mouseIsDown = true;
}

void MainWindow::LabelMouseUp(DraggableLabel* sender, int x, int y)
{
    debugLabel->appendPlainText(QString("%1:   Up:%2,%3").arg(IdentifyFunctionLabel(sender)).arg(x).arg(y));

    if(!mouseIsDown)
    {
        return;
    }

    if(x > panelwidth)
    {
        QWidget* panel = nullptr;
        QPixmap* pixmap = nullptr;
        if(sender == labelSceneNew)
        {
            pixmap = newPixmap;
            panel = panelScenes;
        }
        if(sender == labelSceneFile)
        {
            pixmap = filePixmap;
            panel = panelScenes;
        }
        if(panel != nullptr)
        {
            DraggableLabel* newlabel = new DraggableLabel(panel);
            newlabel->setStyleSheet("background-color: darkgray");
            newlabel->setPixmap(*pixmap);
            newlabel->setAlignment(Qt::AlignCenter);
            newlabel->setGeometry(x, y, 100, 100);  //icons are 96 x 96
            connect(newlabel, SIGNAL(MouseDown(DraggableLabel*,int,int)),
                    this, SLOT(LabelMouseDown(DraggableLabel*,int,int)));
            connect(newlabel, SIGNAL(MouseUp(DraggableLabel*,int,int)),
                    this, SLOT(LabelMouseUp(DraggableLabel*,int,int)));
            connect(newlabel, SIGNAL(MouseMove(DraggableLabel*,int,int)),
                    this, SLOT(LabelMouseMove(DraggableLabel*,int,int)));
            *allScenes << newlabel;
        }
    }

    mouseIsDown = false;
}

void MainWindow::LabelMouseMove(DraggableLabel* sender, int x, int y)
{
    debugLabel->appendPlainText(QString("%1: Move:%2,%3").arg(IdentifyFunctionLabel(sender)).arg(x).arg(y));
}

看你的代码,我猜你应该添加类似 show() 的东西

来自Qt Documenation

If you add a child widget to an already visible widget you must explicitly show the child to make it visible.

它在你的 test() 函数 probabyl 中工作的原因是这段代码在你调用 app.exec() 之前就已经执行了。

newLabel->show()