I want to move a QtWidgets.QtWidget using the mouse (not a QPushButton, QLabel etc.). I've searched everywhere on the web, but couldn't find an answer for this. mousePressEvent seemed to be the way, but it doesn't work.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_hGUI(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
def setupUi(self, hGUI):
hGUI.setObjectName("hGUI")
hGUI.resize(161, 172)
hGUI.setMinimumSize(QtCore.QSize(200, 200))
hGUI.setMaximumSize(QtCore.QSize(200, 200))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
hGUI = QtWidgets.QWidget()
ui = Ui_hGUI()
ui.setupUi(hGUI)
hGUI.show()
sys.exit(app.exec_())
I'm using Python 3.5, I'm creating the GUI using Qt Designer, then translate it to python code.
Edit: I'm trying to move a borderless windows by click on it.
That's a really simple question sir,
Let's say you just have to have an variable that holds the position of your widget and interact with it according to your needs.
This position variable let's call it "oldPos".
Now inside your mouse press you update this position.
By the last but not least, you relate your "oldPos" and your mouseMove actual position and move your widget.
Wallahhhh, here we have a beautiful and simple movable widget by mouse events.
Here is the simplest example.
from PyQt5.QtWidgets import QWidget
class MyMovableWidget(QWidget):
"""WToolBar is a personalized toolbar."""
homeAction = None
oldPos = QPoint()
def __init__(self):
super().__init__()
def mousePressEvent(self, evt):
"""Select the toolbar."""
self.oldPos = evt.globalPos()
def mouseMoveEvent(self, evt):
"""Move the toolbar with mouse iteration."""
delta = QPoint(evt.globalPos() - self.oldPos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = evt.globalPos()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
coolWidget = MyMovableWidget()
coolWidget.show()
sys.exit(app.exec_())
So simple isn't it? :D
I managed to make it work, thanks to #bnaecker for telling me that the code actually creates two widgets, I've replaced some stuff in my code. Basically, just edit the code generated when you translate the .ui to .py so it would only create one widget.
The most changes happened here:
if __name__ == "__main__":
import sys
sys.excepthook = excepthook
app = QtWidgets.QApplication(sys.argv)
hGUI = QtWidgets.QWidget(flags=QtCore.Qt.FramelessWindowHint)
ui = Ui_hGUI()
ui.setupUi(hGUI)
hGUI.show()
sys.exit(app.exec_())
Edited to this:
if __name__ == "__main__":
sys.excepthook = excepthook
app = QtWidgets.QApplication(sys.argv)
hGUI = Ui_hGUI()
sys.exit(app.exec_())
Add self.show() at the end of retranslateUi(self), replace every "hGUI" in the code with "self" or delete it if it's an argument (except for controls like buttons and labels).
Here are both codes, non-working one vs. working one: https://gist.github.com/anonymous/0707b4fef11ae4b31cf56dc78dd3af80
Note: In the new code, the app is called "VirtualMemories".
Related
I need help figuring out how to use the value written in a textbox in PyQT5, and use that value to build an IF statement. Any suggestions on how to do it? I have tried to declare the text in the textbox as a variable and use it in the IF statement but I can't seem to figure it out how to do it properly, and every time i run the code, some exit code shows (-1073741819 (0xC0000005) ).
Summing up, can't use pass the value of the textbox to the variable in order to do an IF statement.
I had this code down below:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QTextEdit
def window():
app = QApplication(sys.argv)
win = QMainWindow()
win.setGeometry(200, 200, 400, 400)
win.setWindowTitle("Register Program")
label = QtWidgets.QLabel(win)
label.setText("Random Text")
label.move(169, 15)
label2 = QtWidgets.QLabel(win)
label2.resize(300, 100)
label2.setText("1- Register new person\n2- See all regestries\n3- See last regestry\n\nPress ESC to exit\n")
label2.move(70, 50)
textbox = QtWidgets.QLineEdit(win)
textbox.setText("")
textbox.resize(250, 25)
textbox.move(70, 250)
button1 = QtWidgets.QPushButton(win)
button1.move(150, 300)
button1.setText("Submit")
button1.clicked.connect(clicked)
button2 = QtWidgets.QPushButton(win)
button2.move(150, 335)
button2.setText("Close")
button2.clicked.connect(close)
win.show()
sys.exit(app.exec_())
def clicked():
inpt = int(window().textbox.text)
if inpt == 1:
print("Hello")
def close():
sys.exit()
window()```
If you're just looking to get user input, there's a builtin static method you can call for requesting input of a particular type: https://doc.qt.io/qt-5/qinputdialog.html#getText
If you want to make your own widget however, you need to use the signals and slots to trigger a python method to store the value. This is easiest to do in a class. You can trigger the method whenever the text changes with the textChanged signal and do whatever you need to do with it.
(Note, I haven't run this as I don't have PyQt5 currently installed, but it should work)
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
# type: (QtWidgets.QWidget) -> None
super(Widget, self).__init__(parent)
self.line_edit = QtWidgets.QLineEdit()
main_layout = QtWidgets.QVBoxLayout()
main_layout.addWidget(self.line_edit)
self.setLayout(main_layout)
self.line_edit.textChanged.connect(self.on_text_changed)
def get_text(self):
return self.line_edit.text()
def on_text_changed(self, text):
print("The text was changed to:", text)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
widget = Widget()
widget.show()
app.exec_()
Edit: Also, to clarify why you're getting an error, QApplication is a singleton. This means there can only ever be one created. If you try to create a second, you'll get an error. The best way to access the current QApplication is to call QApplication.instance(). You also only call app.exec_() once, as once the application is running it will continue to run in the background. You should use signal/slots to interact with the UI and trigger the code you want to run.
I am currently working in a GUI using Python 3.6 and PyQt5, I have a menu bar with 3 menus, one of them is Called Settings in which the user can select the month they want to see, is there a way to check if the selected action changed instead of using
self.actionJanuary.isChecked()
Or
self.actionJanuary.triggered.connect()
As you point out the problem are the many lines of code that you use because it seems that you are creating 12 QActions, but the simplest thing is to iterate for it, the calendar module is used, on the other hand instead of connecting the triggered signal of the QActions it can be used the triggered signal of the QMenu that returns the modified QAction as shown below:
import sys
import calendar
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
menu_months = self.menuBar().addMenu("Settings")
menu_months.triggered.connect(self.on_triggered)
for i in range(1, 13):
name = calendar.month_name[i]
action = menu_months.addAction(name)
action.setCheckable(True)
#QtCore.pyqtSlot(QtWidgets.QAction)
def on_triggered(self, action):
print("{} : {}".format(action.text(), action.isChecked()))
# uncomment if you want to see the status of all actions
"""menu = self.sender()
for action in menu.actions():
print("{} : {}".format(action.text(), action.isChecked()))"""
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
I know this question has been asked in similar ways, but I'm getting lost in the vast world of the many signals I can choose from when using a QSpinBox (or QDoubleSpinBox). I want to connect my function to the editingFinished signal (fine, it works perfectly), but this will not also connect to the arrow-buttons - so I need signals for those as well. I don't want to call my function every time valueChanged is emitted - only when editing is finished, or when the arrows are used.
One way to do this is to reimplement the stepBy method and emit a custom signal. The main advantage of this approach is that it will handle changes made using the up/down keys, as well as the arrow buttons. Here is a basic demo:
import sys
from PyQt4 import QtCore, QtGui
class SpinBox(QtGui.QSpinBox):
stepChanged = QtCore.pyqtSignal()
def stepBy(self, step):
value = self.value()
super(SpinBox, self).stepBy(step)
if self.value() != value:
self.stepChanged.emit()
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.spin = SpinBox()
self.spin.editingFinished.connect(self.handleSpinChanged)
self.spin.stepChanged.connect(self.handleSpinChanged)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.spin)
def handleSpinChanged(self):
print(self.spin.value())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 150, 50)
window.show()
sys.exit(app.exec_())
I am very new to PyQt4 and this question is probably very simple but I have tried many different things and nothing works. I am trying to make a label in PyQt4.
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class Display(QtGui.QWidget):
def __init__(self):
super(Display, self).__init__()
self.time = Time() #Another class in the program
self.ShowFullScreen()
self.setStyleSheet("background-color: black;")
self.show()
self.MainDisplay()
def MainDisplay(self):
self.timedisplay = QtGui.QLabel(self)
self.timedisplay.setStyleSheet("font: 30pt Helvetica; color: white;")
self.timedisplay.setText(time.GetTime())
self.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
GUI = Display()
sys.exit(app.exec())
The label doesn't show up, and there is no error message. What am I doing wrong?
I use PySide and not Qt, but they are supposed to be 99.99% compatible. The main problem is your call to the show() function, which makes the window visible. You have two calls to show. The first time it is called, you have not yet called MainDisplay so the QLabel hasn't been created yet. The second time you call show the window is already visible, so nothing changes.
If you create the widgets first and call show once, at the end, it will work the way you want. With this code the label shows up.
There are other issues:
You will have to change the import statements back the way you had them.
I did not have your Time class, so I just wrote a simple piece of text into the label.
The function ShowFullScreen should be showFullScreen.
The function that runs the event loop in QtApp is named exec_ not exec.
import sys
from PySide import QtCore
from PySide import QtGui
class Display(QtGui.QWidget):
def __init__(self):
super(Display, self).__init__()
self.setStyleSheet("background-color: black;")
self.MainDisplay()
self.showFullScreen()
def MainDisplay(self):
self.timedisplay = QtGui.QLabel(self)
self.timedisplay.setStyleSheet("font: 30pt Helvetica; color: white;")
self.timedisplay.setText("What time is it now?")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
GUI = Display()
sys.exit(app.exec_())
I'm writing in python using Qt
I want to create the application window (with decorations) to occupy the full screen size. Currently this is the code I have:
avGeom = QtGui.QDesktopWidget().availableGeometry()
self.setGeometry(avGeom)
the problem is that it ignores window decorations so the frame is larger... I googled and what not, found this:
http://harmattan-dev.nokia.com/docs/library/html/qt4/application-windows.html#window-geometry
which seems to indicate I need to set the frameGeometry to the avGeom however I haven't found a way to do that. Also, in the comments in the above link it says what I'm after may not be even possible as the programme can't set the frameGeometry before running... If that is the case I just want confirmation that my problem is not solvable.
EDIT:
So I played around with the code a bit and this gives what I want... however the number 24 is basically through trial and error until the window title is visible.... I want some better way to do this... which is window manager independent..
avGeom = QtGui.QDesktopWidget().availableGeometry()
avGeom.setTop(24)
self.setGeometry(avGeom)
Now I can do what I want but purely out of trial and error
Running Ubuntu, using Spyder as an IDE
thanks
Use QtGui.QApplication().desktop().availableGeometry() for the size of the window:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButtonClose = QtGui.QPushButton(self)
self.pushButtonClose.setText("Close")
self.pushButtonClose.clicked.connect(self.on_pushButtonClose_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.pushButtonClose)
titleBarHeight = self.style().pixelMetric(
QtGui.QStyle.PM_TitleBarHeight,
QtGui.QStyleOptionTitleBar(),
self
)
geometry = app.desktop().availableGeometry()
geometry.setHeight(geometry.height() - (titleBarHeight*2))
self.setGeometry(geometry)
#QtCore.pyqtSlot()
def on_pushButtonClose_clicked(self):
QtGui.QApplication.instance().quit()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
I've always found inheritting from the QMainWindow class to be particularly useful. Like this:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class Some_APP(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
### this line here is what you'd be looking for
self.setWindowState(Qt.WindowMaximized)
###
self.show()
def main():
app = QApplication(sys.argv)
some_app = Some_APP()
sys.exit(app.exec_())
if __name__ == "__main__":
main()