带有自定义标题栏的可拖动无框架 PyQt4 Window
Draggable Frameless PyQt4 Window With A Custom Titlebar
我已经使用 mouseclickevent
和 mousemoveevent
使我的应用程序 可拖动。这是当前代码:
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.initUI()
def initUI(self):
self.CentralWidget = QtGui.QStackedWidget()
self.CentralWidget.setFixedHeight(600)
self.setCentralWidget(self.CentralWidget)
self.Main = Main(self)
self.CentralWidget.addWidget(self.Main)
#Set Current Widgets
self.CentralWidget.setCurrentWidget(self.Main)
#Set Background
self.show()
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setStyleSheet("QMainWindow { background-color: \
rgb(0, 0, 0); }")
self.setGeometry(0, 0, 850, 600)
self.setWindowTitle("Folder Locker")
self.Center()
Font = QtGui.QFont()
Font.setPointSize(12)
TitleBar = QtGui.QDockWidget()
Actions = QtGui.QGroupBox()
Title = QtGui.QLabel("Folder Locker")
Title.setFont(Font)
Title.setStyleSheet('color: white')
Title.setAlignment(QtCore.Qt.AlignCenter)
Fake = QtGui.QPushButton()
Fake.setFixedWidth(25)
Fake.setFixedHeight(25)
Fake.setStyleSheet("QPushButton { background-color: \
rgb(0, 0, 0); }")
Fake1 = QtGui.QPushButton()
Fake1.setFixedWidth(25)
Fake1.setFixedHeight(25)
Fake1.setStyleSheet("QPushButton { background-color: \
rgb(0, 0, 0); }")
Font = QtGui.QFont()
Font.setPointSize(12)
Font2 = QtGui.QFont()
Font2.setPointSize(18)
Exit = QtGui.QPushButton("X")
Exit.setFixedWidth(35)
Exit.setFixedHeight(25)
Exit.clicked.connect(self.ExitM)
Exit.setStyleSheet('QPushButton {background-color: \
rgb(0, 0, 0); color: grey;}')
Exit.setFont(Font)
Minimize = QtGui.QPushButton("-")
Minimize.setFixedWidth(25)
Minimize.setFixedHeight(25)
Minimize.clicked.connect(self.MinimizeM)
Minimize.setStyleSheet('QPushButton {background-color: \
rgb(0, 0, 0); color: grey;}')
Minimize.setFont(Font2)
Grid = QtGui.QGridLayout()
Grid.addWidget(Fake, 1, 1)
Grid.addWidget(Fake1, 1, 2)
Grid.addWidget(Title, 1, 3)
Grid.addWidget(Exit, 1, 5)
Grid.addWidget(Minimize, 1, 4)
Actions.setLayout(Grid)
TitleBar.setWidget(Actions)
TitleBar.setFixedHeight(40)
TitleBar.setFloating(False)
TitleBar.setTitleBarWidget(QtGui.QWidget(None))
TitleBar.setStyleSheet("QGroupBox { background-color: \
rgb(0, 0, 0); border: 0px solid rgb(0, 0, 0); }")
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, TitleBar)
self.oldPos = self.pos()
def Center(self):
self.Resolution = QtGui.QDesktopWidget().screenGeometry()
self.move((self.Resolution.width() / 2) - (self.frameSize().width() / 2),
(self.Resolution.height() / 2) - (self.frameSize().height() / 2))
def MinimizeM(self):
self.showNormal()
self.showMinimized()
def ExitM(self):
sys.exit(0)
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
delta = QtCore.QPoint (event.globalPos() - self.oldPos)
#print(delta)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
不幸的是,window 只能通过在我的自定义标题栏 下方轻轻单击来拖动,我希望能够单击 titlebar
是一个 QDockWidget
并使 window 跟随鼠标移动。
如有任何帮助,我们将不胜感激,
谢谢你。
对于您所描述的问题,有几种解决方案,其中之一可能是激活 QDockWidget
的 Qt::WA_TransparentForMouseEvents
属性,使鼠标事件透明传递给下面的小部件,即QMainWindow
,但这会在关闭和最小化按钮上产生不良行为。
所以一个更优雅的解决方案是使用eventFilter方法并过滤事件QEvent::MouseButtonPress
和QEvent::MouseMove,
但是在它们之前必须启用将其他小部件的事件传输到QMainWindow的能力,在这个如果我们要使用 TitleBar、Title 和 self。使用此方法不再需要覆盖 mousePressEvent
和 mouseMoveEvent
方法。
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.initUI()
def initUI(self):
...
TitleBar.installEventFilter(self)
self.installEventFilter(self)
Title.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
self.oldPos = event.globalPos()
elif event.type() == QtCore.QEvent.MouseMove:
delta = QtCore.QPoint(event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
return QtGui.QMainWindow.eventFilter(self, obj, event)
我已经使用 mouseclickevent
和 mousemoveevent
使我的应用程序 可拖动。这是当前代码:
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.initUI()
def initUI(self):
self.CentralWidget = QtGui.QStackedWidget()
self.CentralWidget.setFixedHeight(600)
self.setCentralWidget(self.CentralWidget)
self.Main = Main(self)
self.CentralWidget.addWidget(self.Main)
#Set Current Widgets
self.CentralWidget.setCurrentWidget(self.Main)
#Set Background
self.show()
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setStyleSheet("QMainWindow { background-color: \
rgb(0, 0, 0); }")
self.setGeometry(0, 0, 850, 600)
self.setWindowTitle("Folder Locker")
self.Center()
Font = QtGui.QFont()
Font.setPointSize(12)
TitleBar = QtGui.QDockWidget()
Actions = QtGui.QGroupBox()
Title = QtGui.QLabel("Folder Locker")
Title.setFont(Font)
Title.setStyleSheet('color: white')
Title.setAlignment(QtCore.Qt.AlignCenter)
Fake = QtGui.QPushButton()
Fake.setFixedWidth(25)
Fake.setFixedHeight(25)
Fake.setStyleSheet("QPushButton { background-color: \
rgb(0, 0, 0); }")
Fake1 = QtGui.QPushButton()
Fake1.setFixedWidth(25)
Fake1.setFixedHeight(25)
Fake1.setStyleSheet("QPushButton { background-color: \
rgb(0, 0, 0); }")
Font = QtGui.QFont()
Font.setPointSize(12)
Font2 = QtGui.QFont()
Font2.setPointSize(18)
Exit = QtGui.QPushButton("X")
Exit.setFixedWidth(35)
Exit.setFixedHeight(25)
Exit.clicked.connect(self.ExitM)
Exit.setStyleSheet('QPushButton {background-color: \
rgb(0, 0, 0); color: grey;}')
Exit.setFont(Font)
Minimize = QtGui.QPushButton("-")
Minimize.setFixedWidth(25)
Minimize.setFixedHeight(25)
Minimize.clicked.connect(self.MinimizeM)
Minimize.setStyleSheet('QPushButton {background-color: \
rgb(0, 0, 0); color: grey;}')
Minimize.setFont(Font2)
Grid = QtGui.QGridLayout()
Grid.addWidget(Fake, 1, 1)
Grid.addWidget(Fake1, 1, 2)
Grid.addWidget(Title, 1, 3)
Grid.addWidget(Exit, 1, 5)
Grid.addWidget(Minimize, 1, 4)
Actions.setLayout(Grid)
TitleBar.setWidget(Actions)
TitleBar.setFixedHeight(40)
TitleBar.setFloating(False)
TitleBar.setTitleBarWidget(QtGui.QWidget(None))
TitleBar.setStyleSheet("QGroupBox { background-color: \
rgb(0, 0, 0); border: 0px solid rgb(0, 0, 0); }")
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, TitleBar)
self.oldPos = self.pos()
def Center(self):
self.Resolution = QtGui.QDesktopWidget().screenGeometry()
self.move((self.Resolution.width() / 2) - (self.frameSize().width() / 2),
(self.Resolution.height() / 2) - (self.frameSize().height() / 2))
def MinimizeM(self):
self.showNormal()
self.showMinimized()
def ExitM(self):
sys.exit(0)
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
delta = QtCore.QPoint (event.globalPos() - self.oldPos)
#print(delta)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
不幸的是,window 只能通过在我的自定义标题栏 下方轻轻单击来拖动,我希望能够单击 titlebar
是一个 QDockWidget
并使 window 跟随鼠标移动。
如有任何帮助,我们将不胜感激, 谢谢你。
对于您所描述的问题,有几种解决方案,其中之一可能是激活 QDockWidget
的 Qt::WA_TransparentForMouseEvents
属性,使鼠标事件透明传递给下面的小部件,即QMainWindow
,但这会在关闭和最小化按钮上产生不良行为。
所以一个更优雅的解决方案是使用eventFilter方法并过滤事件QEvent::MouseButtonPress
和QEvent::MouseMove,
但是在它们之前必须启用将其他小部件的事件传输到QMainWindow的能力,在这个如果我们要使用 TitleBar、Title 和 self。使用此方法不再需要覆盖 mousePressEvent
和 mouseMoveEvent
方法。
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.initUI()
def initUI(self):
...
TitleBar.installEventFilter(self)
self.installEventFilter(self)
Title.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
self.oldPos = event.globalPos()
elif event.type() == QtCore.QEvent.MouseMove:
delta = QtCore.QPoint(event.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
return QtGui.QMainWindow.eventFilter(self, obj, event)