如何在QT中创建一个可拖动的(无边框和标题栏)顶层窗口

4
我很乐意帮助您创建一个具有以下特点的Qt顶级窗口。该窗口必须:
  1. 无边框,无标题,并处于桌面上所有其他窗口的最上层(容易实现)
  2. 可通过单击并在其内部拖动来移动窗口(需要帮助)
  3. 在拖动时被限制在桌面的顶部边缘(相对容易实现)
基本上,我想将我们的QT应用程序折叠成位于桌面顶部边缘的顶级图标。
1个回答

6

你可以在这里找到第一部分的答案,关于第二部分的答案则在这里

将两部分内容结合起来并添加最后一部分很简单。

以下是实现方法:

#include <QtGui>

class W: public QWidget
{
    Q_OBJECT

设置一个无边框的小部件,内含几个按钮用于锁定/解锁和退出:

    public:
        W(QWidget *parent=0)
            : QWidget(parent, Qt::FramelessWindowHint), locked(false)
        {
            QPushButton *lock   = new QPushButton("Lock");
            QPushButton *unlock = new QPushButton("Unlock");
            QPushButton *quit   = new QPushButton("&Quit");

            connect(lock,   SIGNAL(clicked()), this, SLOT(lock()));
            connect(unlock, SIGNAL(clicked()), this, SLOT(unlock()));
            connect(quit, SIGNAL(clicked()),
                    QApplication::instance(), SLOT(quit()));

            QHBoxLayout *l = new QHBoxLayout;
            l->addWidget(lock);
            l->addWidget(unlock);
            l->addWidget(quit);
            setLayout(l);
        }

    public slots:
        void lock() {
          locked = true;
          move(x(), 0); // move window to the top of the screen
        }
        void unlock() { locked = false; }

处理鼠标操作:

    protected:
        void mousePressEvent(QMouseEvent *evt)
        {
            oldPos = evt->globalPos();
        }

        void mouseMoveEvent(QMouseEvent *evt)
        {
            const QPoint delta = evt->globalPos() - oldPos;
            if (locked)
                // if locked, ignore delta on y axis, stay at the top
                move(x()+delta.x(), y()); 
            else
                move(x()+delta.x(), y()+delta.y());
            oldPos = evt->globalPos();
        }

    private:
        bool locked;
        QPoint oldPos;
};

它基本上可以工作。不幸的是,无边框小部件仍然有一个框架,我怀疑这是Window 7的属性。这个“框架”的顶部仍然可以拖动。框架的其他边缘则不能。 - Olumide
刚在Windows 7上运行了这个程序(Qt 5),使用上述代码(已经为Qt5重新编写了包含文件),我没有看到边框。 - Mat
我指的是框架。我仍在使用Qt 4。请参阅http://nicug.blogspot.co.uk/2011/03/qt-windows-7-extend-frame-into-client.html以获取建议的解决方法。 - Olumide
我猜可能是Qt5/Qt4的问题,但这听起来有点奇怪。即使我从QMainWindow或QDialog派生而来,而不是一个普通的QWidget,上面的代码也没有任何边框或框架。奇怪。 - Mat
在 Windows 上这很好用。但是在 Linux Mint 上,如果小部件在第二个屏幕上,move()函数就不起作用了,并且小部件被限制在第二个屏幕的边界内。[应用程序中创建的其他 QWidgets 没有这个问题并且可以在屏幕之间移动,但是拖动是通过单击小部件的顶部栏来完成的] - David Casper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接