I want to make a specific button in PyQt toolbar appeared as pressed(with blue background). Suppose when I hit the toolbar button I want it to be appeared as pressed
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 700, 700)
self.setWindowTitle('Rich Text Editor')
self.statusBar = QStatusBar()
self.textEdit = QtGui.QTextEdit()
self.setCentralWidget(self.textEdit)
self.setStatusBar(self.statusBar)
self.home()
def home(self):
changeBoldActionTB = \
QtGui.QAction(QtGui.QIcon('bold-text-option.png'),
'Make the text bold', self)
changeBoldActionTB.triggered.connect(self.changeBold)
self.formatbar = QToolBar()
self.addToolBar(Qt.TopToolBarArea, self.formatbar)
self.formatbar.addAction(changeBoldActionTB)
self.show()
def changeBold(self):
pass
#I think this does't matter
def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
run()
I have two toolbars.I am planning to use cursorPositionChanged to do this but still is there a way in PyQt to do this
reproduible code:
https://files.fm/u/h4c2amdx
Instead of using QAction you must use QToolButton and set the checkable property to True:
toolButton.setCheckable(True)
Example:
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setWindowTitle('Rich Text Editor')
self.statusBar = QStatusBar(self)
self.textEdit = QtGui.QTextEdit(self)
self.setCentralWidget(self.textEdit)
self.setStatusBar(self.statusBar)
self.home()
def home(self):
toolButton = QToolButton(self)
toolButton.setIcon(QtGui.QIcon('bold-text-option.png'))
toolButton.setCheckable(True)
toolButton.toggled.connect(self.onToggled)
self.formatbar = QToolBar(self)
self.addToolBar(Qt.TopToolBarArea, self.formatbar)
self.formatbar.addWidget(toolButton)
def onToggled(self, checked):
print(checked)
Screenshots:
Plus: To set the value manually and to obtain the status the following instructions are used:
toolButton.setChecked(True) # set State
print(toolButton.isChecked()) # get State
toolButton.toggle() # change state
Actions also have a checable flag and they can act as a toggle switch. Sorry, I don’t know English. So I showed it with code.
# add this code before self.formatbar = QToolBar()
# and create img file blue_bold-text-option.png
self.changeBoldActionTB.setCheckable(True)
icon = QIcon()
icon.addFile('bold-text-option.png', QSize(), QIcon.Normal, QIcon.Off)
icon.addFile('blue_bold-text-option.png', QSize(), QIcon.Normal, QIcon.On)
self.changeBoldActionTB.setIcon(icon)
Related
I am trying to build a hover Dialog but i am stuck at the interaction between QComboBox selection and QDialog's leaveEvent. it looks like when i try to click on combobox to select something, it triggers a leaveEvent which then hides my QDialog. Why is this happening? What can i try to ensure that the Dialog is only hidden when I move my mouse outside of the Dialog?
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
class hoverDialog(QDialog):
def __init__(self, parent=None):
super().__init__()
self.setAttribute(Qt.WA_DeleteOnClose)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.v = QVBoxLayout()
self.combobox = QComboBox()
self.combobox.addItems(['Work-around','Permanent'])
self.textedit = QPlainTextEdit()
self.v.addWidget(self.combobox)
self.v.addWidget(self.textedit)
self.setLayout(self.v)
#self.setMouseTracking(True)
def leaveEvent(self, event):
self.hide()
return super().leaveEvent(event)
class Table(QWidget):
def __init__(self, parent=None):
super().__init__()
self.label4 = QLabel()
self.label4.setText("hover popup")
self.label4.installEventFilter(self)
self.checkbox1 = QCheckBox()
self.pushButton3 = QPushButton()
self.pushButton3.setText('Generate')
self.pushButton3.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
self.pushButton3.clicked.connect(self.buttonPressed)
self.hbox5 = QHBoxLayout()
self.hbox5.addWidget(self.checkbox1)
self.hbox5.addWidget(self.label4)
self.hbox5.addWidget(self.pushButton3)
self.vbox1 = QVBoxLayout()
self.vbox1.addLayout(self.hbox5)
self.setLayout(self.vbox1)
self.autoResolve = hoverDialog(self)
def eventFilter(self, obj, event):
if obj == self.label4 and event.type() == QtCore.QEvent.Enter and self.autoResolve.isHidden():
self.onHovered()
return super().eventFilter(obj, event)
def onHovered(self):
pos = QtGui.QCursor.pos()
self.autoResolve.move(pos)
self.autoResolve.show()
def buttonPressed(self):
if self.checkbox.isChecked():
print('do something..')
if __name__ == '__main__':
app = QApplication(sys.argv)
form = Table()
form.show()
app.exec_()
Looking at the sources, I believe that the origin of the problem is in Qt's behavior whenever a new popup widget is shown.
I cannot guarantee this at 100%, but in any case the simplest solution is to hide the widget only if the combo popup is not shown:
def leaveEvent(self, event):
if not self.combobox.view().isVisible():
self.hide()
Note that your approach is not really perfect: since the dialog could be shown with a geometry that is outside the current mouse position, it will not be able to hide itself until the mouse actually enters it. You should probably filter FocusOut and WindowDeactivate events also.
I found some code on here that shows an example of how you can get the window to resize when the widget is hidden, and it works for me. Here is the code:
from PyQt4 import QtCore, QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
super(MainWindow, self).__init__()
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def startup(self):
self.show()
sys.exit(self.app.exec_())
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
myApp = MainWindow()
myApp.startup()
I then tried to modify this to match my existing code by separating the mainWindow class and the widget class. Here is the code that does that.
from PySide import QtGui,QtCore
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.setCentralWidget(self.w)
self.show()
class testW(QtGui.QWidget):
def __init__(self,parent):
super(testW,self).__init__()
self.parent = parent
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.button.setChecked(True);
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myApp = MainWindow()
sys.exit(app.exec_())
#time.sleep(1)
Running the first code does what I want it to. After I hide the widget, the window resizes to the correct size. The second implementation of the code does not shrink and expand the window when I hide and show the widget. Is this because the MainWindow is in a separate class?
Use size policies for your widgets. For your example you can change UI creation code as follows:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.w.setSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding
)
self.setCentralWidget(self.w)
self.show()
Please note new setSizePolicy call which say Qt layout engine how to change the size of your widget according to its content.
Unfortunately QMainWindow does not respect sizeHint automatically, but it is calculated properly, so you can adjustSize manually:
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.parent.adjustSize)
You do not need to resize your widget itself, because it will be resized according to the policy. Even sizeHint will be calculated automatically so you need only to call adjustSize of QMainWindow.
PS: I used PySide2 instead of PySide so the imports are different a little bit:
from PySide2 import QtWidgets, QtCore
I am making Multi-Page application in PyQt4, so whenever user does specific action (clicking a button for example) there is an update in widgets.
For example, There are 5 widgets and one button:
3 widgets are hidden, 2 widgets are shown.
Whenever i click the button, it will hide 2 widgets, and show those 3.
So in code, it should be something like this:
# startup
def somefunc(self):
widget1 = QtGui.QLabel("Widget1", self)
widget2 = QtGui.QLabel("Widget2", self)
widget3 = QtGui.QLabel("Widget3", self)
widget4 = QtGui.QLabel("Widget4", self)
widget5 = QtGui.QLabel("Widget5", self)
widget1.setHidden()
widget2.setHidden()
widget3.setHidden()
widget4.show()
widget5.show()
btn = QtGui.QPushButton("Click", self)
btn.clicked.connect(self.SomeotherFunc)
# My Question: (Code down below doesn't work, it's for example)
def SomeotherFunc(self):
self.somefunc.widget1.Show()
self.somefunc.widget1.Show()
self.somefunc.widget1.Show()
self.somefunc.widget4.setHidden()
self.somefunc.widget5.setHidden()
Full Code:
import sys
from PyQt4 import QtGui, QtCore
import resources
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(0, 0, 1280, 800)
self.setWindowTitle("E.S Quiz")
self.home()
def home(self):
pic = QtGui.QLabel(self)
pic.setGeometry(0, 0, 1280, 800)
pic.setPixmap(QtGui.QPixmap(":/images/background.png"))
btn = QtGui.QPushButton("", self)
btn.resize(150, 120)
btn.move(600, 400)
btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
btn.setObjectName('btn')
btn.setStyleSheet("#btn {background-image: url(':/images/Button1.png'); border: none; }"
"#btn:hover { background-image: url(':/images/Button1Hover.png'); }"
"#btn:pressed { background-image: url(':/images/Button1Press.png'); }")
btn.clicked.connect(self.test)
self.show()
def test(self):
print "Here"
def startup():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
startup()
Question:
How do i modify some functions widgets from another function?
You need to store references to the subwidgets on the main window using self
def func(self):
self.btn = QPushButton(...)
...
def other_func(self):
self.btn.setText('Hello')
I've edited your code. I believe this will do the job. Just push the button, and see the label disappear. Have fun :-)
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(40, 80, 1280, 800)
# You should make a 'mainWidget' that
# serves as a container for all your other
# widgets.
self.mainWidget = QtGui.QWidget()
self.setCentralWidget(self.mainWidget)
self.setWindowTitle("E.S Quiz")
self.home()
self.show()
def home(self):
# Make the label
pic = QtGui.QLabel(parent = self.mainWidget)
pic.setText("My label")
pic.setGeometry(0, 0, 1280, 800)
#pic.setPixmap(QtGui.QPixmap(":/images/background.png"))
# Make a label that will disappear when
# you push the button.
self.myLabel = QtGui.QLabel(parent = self.mainWidget)
self.myLabel.setText("My removable label")
self.myLabel.setGeometry(40,40,200,100)
# Make the button
self.btn = QtGui.QPushButton(parent = self.mainWidget)
self.btn.setCheckable(True)
self.btn.setText("My button")
self.btn.resize(150, 120)
self.btn.move(600, 400)
self.btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.btn.setObjectName('btn')
# self.btn.setStyleSheet("#btn {background-image: url(':/images/Button1.png'); border: none; }"
# "#btn:hover { background-image: url(':/images/Button1Hover.png'); }"
# "#btn:pressed { background-image: url(':/images/Button1Press.png'); }")
self.btn.clicked.connect(self.btnAction)
def btnAction(self, pressed):
print("Button pushed")
if(pressed):
self.myLabel.setVisible(False)
else:
self.myLabel.setVisible(True)
def startup():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
startup()
I started reading the zetcode tutorial for PyQt4 (http://zetcode.com/tutorials/pyqt4/firstprograms/) and I was doing the tooltip part and all I did was copy and paste this bit of code. When I went to run it, the push button did not display in the window. Any reason as to why this might be? new to PyQt4 and Qt in general.
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
btn = QtGui.QPushButton('Button, self')
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Tooltips')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Replace following line:
btn = QtGui.QPushButton('Button, self')
with:
btn = QtGui.QPushButton('Button', self)
btn = QtGui.QPushButton('Button, self')
supposed to be:
btn = QtGui.QPushButton('Button', self)
i'd like to learn PyQt by writing a simple game. the first widget would have buttons like "New game", "Quit", etc. i am having trouble understanding how to transition from that menu widget to a new one.
for instance, if i were to click New Game, how do i have a new widget appear that replaces the old one and asks for the user's name? the way i am approaching it now is something like
Form = QtGui.QWidget()
ui = uiMainMenu()
ui.setupUi(Form)
Form.show()
then once newGameButton is pressed it would go to a subroutine...
Form2 = QtGui.QWidget()
ui2 = uiNewGame()
ui2.setupUi(Form2)
Form2.show()
i'm not asking for all the code, just an explanation as to how i should be approaching the problem, because the code above ain't doing squat.
thanks!
if you want to switch between forms then you can use QStackedWidget.
Below you can find a working sample code:
import sys
from functools import partial
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Form1(QWidget):
showForm2Signal = pyqtSignal()
def __init__(self, parent=None):
super(Form1, self).__init__(parent)
self.newGameButton = QPushButton("New Game", self)
self.quitButton = QPushButton("Quit", self)
layout = QVBoxLayout(self)
layout.addWidget(QLabel("<html>My Game<br>Start Page</html>"))
layout.addWidget(self.newGameButton)
layout.addWidget(self.quitButton)
self.newGameButton.clicked.connect(self.showForm2Signal.emit)
self.quitButton.clicked.connect(qApp.quit)
class Form2(QWidget):
showForm1Signal = pyqtSignal()
def __init__(self, parent=None):
super(Form2, self).__init__(parent)
self.backButton = QPushButton("Back", self)
layout = QVBoxLayout(self)
layout.addWidget(QLabel("New Game Started!"))
layout.addWidget(self.backButton)
self.backButton.clicked.connect(self.showForm1Signal.emit)
class MainWidget(QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.stack = QStackedWidget()
layout = QVBoxLayout(self)
layout.addWidget(self.stack)
self.form1 = Form1(self)
self.form2 = Form2(self)
self.stack.addWidget(self.form1)
self.stack.addWidget(self.form2)
self.form1.showForm2Signal.connect(partial(self.stack.setCurrentWidget,
self.form2))
self.form2.showForm1Signal.connect(partial(self.stack.setCurrentWidget,
self.form1))
self.stack.setCurrentWidget(self.form1)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWidget()
w.show()
app.exec_()
sys.exit()
If you only want to ask the name to the user then you can use a QDialog widget.