I have made an application with a Qmenubar, when i trigger it doesn't do anything and i can't figure out why?
class Layout(QMainWindow):
def __init__(self):
super().__init__()
self.setObjectName("Patient/Doctor booking app")
self.resize(600, 1000)
menu = self.menuBar()
self.fileMenu = menu.addMenu('Admin area')
self.enterAppointments = QAction( 'Enter appointments', self)
self.fileMenu.addAction(self.enterAppointments)
self.enterAppointments = QAction(self)
self.enterAppointments.triggered[QAction].connect(self.test)
def test(self):
print("trigger test")
Related
Here in my sample program i want to display my gif upto my process is completed.After my process is completed automatically my gif will close.for that i used here threading function but i am not able to show gif.But i don't have any idea where i did mistake in this program,So can any one please check this program and please guide me.Thank you in advance.
Given below is my code:
import sys
from PyQt4 import QtGui
import os
class DialogThread(QtCore.QThread):
def __init__(self, interval=1):
self.interval = interval
thread = threading.Thread(target=self.run, args=())
thread.daemon = True # Daemonize thread
thread.start() # Start the execution
def run(self):
global savingDataFlag,dialog_gif
""" Method that runs forever """
while True:
if savingDataFlag == True:
dialog_gif.run()
print 'in saving data true loop'
else:
dialog_gif.close()
print 'in saving data false loop'
time.sleep(3)
class Dialog(QtGui.QDialog):
def __init__(self, parent = None):
super(Dialog, self).__init__(parent)
self.setStyleSheet("QDialog {background-color:black; color:white }")
self.label1 = QtGui.QLabel(
text="Please Wait while It Is Processing The Data...",
font=QtGui.QFont("Times", 20,weight=QtGui.QFont.Bold)
)
self.label21 = QtGui.QLabel()
vbox1 = QtGui.QVBoxLayout(self)
vbox1.addWidget(self.label1)
vbox1.addWidget(self.label21)
self.resize(640, 480)
#QtCore.pyqtSlot()
def show_gif(self):
movie = QtGui.QMovie(
"./img/loading1.gif",
parent=self
)
self.label21.setMovie(movie)
movie.start()
self.exec_()class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
okButton = QtGui.QPushButton("Save")
cancelButton = QtGui.QPushButton("Cancel")
okButton.clicked.connect(self.save)
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QtGui.QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Buttons')
self.show()
def save(self):
self.d1 = QtGui.QWidget()
self.form1 = QtGui.QFormLayout(self.d1)
self.name_file = QtGui.QLabel(("File Name:"))
self.line_edit1 = QtGui.QLineEdit()
self.saveBtn1 = QtGui.QPushButton(("Save"))
self.saveBtn1.clicked.connect(self.saveModelWidget)
self.canclebtn = QtGui.QPushButton(("Cancel"))
self.form1.addRow(self.name_file, self.line_edit1)
self.form1.addRow( self.canclebtn,self.saveBtn1)
self.d1.setWindowTitle("Enter Grids")
self.d1.setGeometry(450,300,500,100)
self.d1.show()
def saveModelWidget(self):
self.savefile()
def savefile(self):
self.d1.close()
self.save_text = self.line_edit1.text()
self.currFilePath = os.getcwd()
if self.save_text.endsWith(".csv"):
file_Name= self.save_text
with open(file_Name, 'w+')as f:
dir_path1 =os.getcwd()
save_filename = os.path.join(dir_path1,file_Name)
print "prrocess start"
# here some execution
# when i click the save button i want to display the gif file till to complete the process in save file
print "process ends"
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You are using QThread with the threading module, and the QThread does not use it since it never starts it, instead you are using threading to execute the run () method. On the other hand overwriting the run method of QThread is a method but many limits many things, instead I will create a worker that will live in another thread. Another error is that movie is a local variable that will be deleted so it will not show, the solution is to pass it a parent. Considering the above the solution is:
import os
import sys
import threading
from PyQt4 import QtCore, QtGui
class SaveWorker(QtCore.QObject):
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
#QtCore.pyqtSlot(str)
def save_file(self, filename):
self.started.emit()
for i in range(100000):
print(i)
with open(filename, 'w+')as f:
print(filename)
# some execution
self.finished.emit()
class GifDialog(QtGui.QDialog):
def __init__(self, parent = None):
super(GifDialog, self).__init__(parent)
self.setStyleSheet("QDialog {background-color:black; color:white }")
self.label1 = QtGui.QLabel(
text="Please Wait while It Is Processing The Data...",
font=QtGui.QFont("Times", 20,weight=QtGui.QFont.Bold)
)
self.label2 = QtGui.QLabel()
vbox = QtGui.QVBoxLayout(self)
vbox.addWidget(self.label1)
vbox.addWidget(self.label2)
#QtCore.pyqtSlot()
def show_gif(self):
movie = QtGui.QMovie(
"./img/loading1.gif",
parent=self
)
self.label2.setMovie(movie)
movie.start()
self.show()
class FormDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(FormDialog, self).__init__(parent)
self.setWindowTitle("Enter Grids")
self.line_edit = QtGui.QLineEdit()
self.savebtn = QtGui.QPushButton(
text="Save",
clicked=self.save
)
self.cancelbtn = QtGui.QPushButton("Cancel")
#self.savebtn.clicked.connect(self.saveModelWidget)
flay = QtGui.QFormLayout(self)
flay.addRow("File Name:", self.line_edit)
flay.addRow(self.cancelbtn, self.savebtn)
self.worker = SaveWorker()
self.gif_dialog = GifDialog(self)
self.worker.started.connect(self.gif_dialog.show_gif)
self.worker.finished.connect(self.close)
#QtCore.pyqtSlot()
def save(self):
filename = str(self.line_edit.text())
if filename.endswith(".csv"):
save_filename = os.path.join(os.getcwd(), filename)
thread = threading.Thread(target=self.worker.save_file, args=(save_filename,))
thread.daemon = True
thread.start()
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
okButton = QtGui.QPushButton(
text="Save",
clicked=self.on_clicked
)
cancelButton = QtGui.QPushButton("Cancel")
# okButton.clicked.connect(self.save)
hbox = QtGui.QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QtGui.QVBoxLayout(self)
vbox.addStretch(1)
vbox.addLayout(hbox)
#QtCore.pyqtSlot()
def on_clicked(self):
dialog = FormDialog()
dialog.exec_()
def main():
app = QtGui.QApplication(sys.argv)
dialog = Example()
dialog.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I would like to ask how to make the text in QTextEdit scoll, to achieve an animational effect. The animational effect should be something like what in the video shows: https://www.youtube.com/watch?v=MyeuGdXv4XM
With PyQt I want to get this effect:
The text should be scolled automatically at a speed of 2 lines/second downwards, till it reaches the end and stops.
In my code below, when the button is clicked, the text is shown in QTextEdit-Widget. The text is very long, so that the scroll bar is shown.
My Problem:
I dont know how to make the animation effect. Thus I would like to ask your help to correct my code.
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
import time
list_longText = [" long text 1 - auto scrolling " * 1000, " long text 2 - auto scrolling " * 2000]
class Worker(QObject):
finished = pyqtSignal()
strTxt = pyqtSignal(str)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
#pyqtSlot()
def onJob(self):
for i in range(2):
self.strTxt.emit(list_longText[i])
time.sleep(2)
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setFixedSize(600, 400)
self.setObjectName("window")
self.initUI()
def initUI(self):
self.txt = QTextEdit("", self)
self.btn = QPushButton("Button", self)
self.btn.clicked.connect(self.start)
self.layout = QHBoxLayout(self)
self.layout.addWidget(self.txt)
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
self.show()
def start(self):
self.thread = QThread()
self.obj = Worker()
self.obj.strTxt.connect(self.showText)
self.obj.moveToThread(self.thread)
self.obj.finished.connect(self.thread.quit)
self.thread.started.connect(self.obj.onJob)
self.thread.start()
def showText(self, str):
self.txt.setText("{}".format(str))
self.autoScroll()
def autoScroll(self):
vsb = self.txt.verticalScrollBar()
if vsb.value() <= vsb.maximum():
vsb.setValue(vsb.value() + 2)
time.sleep(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
sys.exit(app.exec_())
Thanks very much for the help!
The task you want is not heavy, it is periodic so using a thread is inappropriate, for this task we can use QVariantAnimation.
The other part is to create a method that moves to a certain line of text for it we use QTextCursor next to findBlockByLineNumber() of QTextDocument.
And for the last one we must start moving to the last initial visible for it we use the cursorForPosition() method through the size of the viewport().
longText = "\n".join(["{}: long text - auto scrolling ".format(i) for i in range(100)])
class AnimationTextEdit(QTextEdit):
def __init__(self, *args, **kwargs):
QTextEdit.__init__(self, *args, **kwargs)
self.animation = QVariantAnimation(self)
self.animation.valueChanged.connect(self.move)
#pyqtSlot()
def startAnimation(self):
self.animation.stop()
lines_per_second = 2
self.moveToLine(0)
p = QPoint(self.viewport().width() - 1, self.viewport().height() - 1)
cursor = self.cursorForPosition(p)
self.animation.setStartValue(cursor.blockNumber())
self.animation.setEndValue(self.document().blockCount()-1)
self.animation.setDuration(self.animation.endValue()*1000/lines_per_second)
self.animation.start()
#pyqtSlot(QVariant)
def move(self, i):
cursor = QTextCursor(self.document().findBlockByLineNumber(i))
self.setTextCursor(cursor)
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setFixedSize(600, 400)
self.txt = AnimationTextEdit(self)
self.btn = QPushButton("Start", self)
self.layout = QHBoxLayout(self)
self.layout.addWidget(self.txt)
self.layout.addWidget(self.btn)
self.txt.append(longText)
self.txt.move(0)
self.btn.clicked.connect(self.txt.startAnimation)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Update:
if you want a continuous movement you must use verticalScrollBar():
longText = "\n".join(["{}: long text - auto scrolling ".format(i) for i in range(100)])
class AnimationTextEdit(QTextEdit):
def __init__(self, *args, **kwargs):
QTextEdit.__init__(self, *args, **kwargs)
self.animation = QVariantAnimation(self)
self.animation.valueChanged.connect(self.moveToLine)
#pyqtSlot()
def startAnimation(self):
self.animation.stop()
self.animation.setStartValue(0)
self.animation.setEndValue(self.verticalScrollBar().maximum())
self.animation.setDuration(self.animation.endValue()*4)
self.animation.start()
#pyqtSlot(QVariant)
def moveToLine(self, i):
self.verticalScrollBar().setValue(i)
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setFixedSize(600, 400)
self.txt = AnimationTextEdit(self)
self.btn = QPushButton("Start", self)
self.layout = QHBoxLayout(self)
self.layout.addWidget(self.txt)
self.layout.addWidget(self.btn)
self.txt.append(longText)
self.txt.moveToLine(0)
self.btn.clicked.connect(self.txt.startAnimation)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
I have a few questions.
How do i properly get settings from the child window when i press 'Print' button?
How do i close the Settings window and save/commit changes only when user presses 'OK' vs 'Cancel' which just closes the dialog and dismisses the changes.
Settings Window
import sys
from PySide import QtGui, QtCore
class SettingsWindow(QtGui.QDialog):
def __init__(self, parent=None):
super(SettingsWindow, self).__init__(parent)
self.resize(200, 150)
self.setWindowTitle('Settings')
self.initUI()
def initUI(self):
lb_max = QtGui.QLabel('Max')
self.ui_max = QtGui.QSpinBox()
self.ui_max.setValue(5)
lb_min = QtGui.QLabel('Min')
self.ui_min = QtGui.QSpinBox()
self.ui_min.setValue(10)
lb_count = QtGui.QLabel('Count')
self.ui_count = QtGui.QSpinBox()
self.ui_count.setValue(25)
self.buttons = QtGui.QDialogButtonBox();
self.buttons.setOrientation(QtCore.Qt.Horizontal)
self.buttons.setStandardButtons(QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel)
self.buttons.layout().setDirection(QtGui.QBoxLayout.LeftToRight)
grid = QtGui.QGridLayout()
grid.setContentsMargins(10,10,10,10)
grid.addWidget(lb_max,0,0)
grid.addWidget(self.ui_max,0,1)
grid.addWidget(lb_min,1,0)
grid.addWidget(self.ui_min,1,1)
grid.addWidget(lb_count,2,0)
grid.addWidget(self.ui_count,2,1)
grid.addWidget(self.buttons,3,1)
self.setLayout(grid)
Main Window
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(200, 150)
self.setWindowTitle('Assets')
self.initUI()
def initUI(self):
self.mi_settings = QtGui.QAction('Settings', self)
self.mi_settings.triggered.connect(self.open_settings)
self.ui_button = QtGui.QPushButton('Print')
self.ui_button.clicked.connect(self.clicked_button)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(self.mi_settings)
grid = QtGui.QVBoxLayout()
grid.setContentsMargins(10,10,10,10)
grid.addWidget(self.ui_button)
main_widget = QtGui.QWidget()
main_widget.setLayout(grid)
self.setCentralWidget(main_widget)
def open_settings(self):
win = SettingsWindow()
win.exec_()
def clicked_button(self):
print 'Settings'
print '\tMax: '
print '\tMin: '
print '\tCount: '
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = MainWindow()
# ex = SettingsWindow()
ex.show()
sys.exit(app.exec_())
Firstly, you need to connect up the buttons in the dialog, so that you can tell whether the user cancelled it or not:
class SettingsWindow(QtGui.QDialog):
...
def initUI(self):
...
self.buttons = QtGui.QDialogButtonBox()
...
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
Secondly, you should think about how you set the defaults in the dialog, and how you reset/retrieve the current values. One way to do this would be to have a central settings dictionary where you store the values, with the dialog being used to update it from user input:
class SettingsWindow(QtGui.QDialog):
...
def getValues(self):
return {
'max': self.ui_max.value(),
'min': self.ui_min.value(),
'count': self.ui_count.value(),
}
def setValues(self, settings):
self.ui_max.setValue(settings['max'])
self.ui_min.setValue(settings['min'])
self.ui_count.setValue(settings['count'])
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
...
# default values
self.settings = {
'max': 5,
'min': 10,
'count': 25,
}
def open_settings(self):
win = SettingsWindow()
# reset from current values
win.setValues(self.settings)
if win.exec_() == QtGui.QDialog.Accepted:
# update only if user clicked ok
self.settings.update(win.getValues())
def clicked_button(self):
print 'Settings:'
for key in 'max', 'min', 'count':
print '\t%s = %s' % (key.title(), self.settings[key])
There are numerous ways to solve this kind of problem, but this should give you the general idea.
You can check the result of the exec_() command to see whether the dialog was accepted or rejected. If it was accepted, you can read the values of the GUI controls
win = SettingsWindow()
r = win.exec_()
if r:
min_val = win.ui_min.value()
max_val = win.ui_max.value()
cnt_val = win.ui_max.value()
I just started with programming, started using Python and PyQt4. And got this error:
QCoreApplication::exec: The event loop is already running
Basically i wanted to write a function which, when you press a button, opens a new gui window(while the previous one wouldnt exist at that point) with completely new layout.
Is there a way how to fix the script or write it in another way to get the outcome?
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
def home(self):
btn = QtGui.QPushButton("Quit", self)
btn.clicked.connect(QtCore.QCoreApplication.instance() .quit)
btn.resize(250,50)
btn.move(100,600)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
btn = QtGui.QPushButton("Start", self)
btn.clicked.connect(self.redirect_window)
btn.resize(250,50)
btn.move(100,200)
btn.setStyleSheet('QPushButton{background-color:#8A0808;color:#000000;font-size:25px;border:5px}')
extractAction = QtGui.QAction(QtGui.QIcon("exitb.png"), "Exit the application.", self)
extractAction.triggered.connect(self.close_appllication)
self.toolBar = self.addToolBar("ToolBar")
self.toolBar.addAction(extractAction)
checkBox = QtGui.QCheckBox("Enlarge Window", self)
checkBox.move(100, 25)
checkBox.stateChanged.connect(self.enlarge_window)
self.show()
def redirect_window(self):
class startWindow(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50 , 1280, 720)
self.setWindowTitle("Main/Start")
self.setWindowIcon(QtGui.QIcon("smili.png"))
extractAction = QtGui.QAction("Exit", self)
extractAction.setShortcut("Ctrl+Q")
extractAction.setStatusTip("Press to leave the app.")
extractAction.triggered.connect(self.close_appllication)
self.statusBar()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("Menu")
fileMenu.addAction(extractAction)
self.home()
main()
def enlarge_window(self, state):
if state == QtCore.Qt.Checked:
self.setGeometry(50,50,1920,1080)
else:
self.setGeometry(50,50,1280,720)
def close_appllication(self):
print("Shutting down!")
sys.exit()
def main():
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
main()
here is my question details: I have these widgets - QMenuBar, QTableWidget and QToolbar. Here is my code sample:
import sys
from PySide import QtGui
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.header_lbls = ['Name', 'Second Name', 'Surname', 'Birth Date', 'Phone Number', 'Skype', 'E-mail']
self.table = QtGui.QTableWidget(10, 7)
self.table.setHorizontalHeaderLabels(self.header_lbls)
self.setCentralWidget(self.table)
#ACTIONS
self.createActions()
#MENUBAR
self.createMenus()
#TOOLBAR
self.createToolbar()
#STATUSBAR
self.creatStatusbar()
def contextMenuEvent(self, event):
self.menu = QtGui.QMenu(self.table)
self.menu.addAction(self.aboutAct)
self.menu.exec_(QtGui.QCursor.pos())
def createActions(self):
self.exitAct = QtGui.QAction('E&xit', self, shortcut='Ctrl+Q',
statusTip='Exit the application', triggered=app.exit)
def createMenus(self):
self.menubar = self.menuBar()
self.fileMenu = self.menuBar().addMenu("&File")
self.fileMenu.addAction(self.exitAct)
def createToolbar(self):
self.toolbar = self.addToolBar('Toolbar')
self.toolbar.addAction(self.settingsAct)
self.toolbar.addSeparator()
self.toolbar.addAction(self.exitAct)
def creatStatusbar(self):
self.statusBar()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Example()
window.setGeometry(80, 80, 800, 600)
window.show()
sys.exit(app.exec_())
The question is: How make QMenu like in Microsoft Excel for example (I mean only add/delete rows/coloumns). Thanks in advance.
Use the customContextMenuRequested signal of the table's header-views:
class Example(QtGui.QMainWindow):
def __init__(self):
...
header = self.table.horizontalHeader()
header.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
header.customContextMenuRequested.connect(self.handleHeaderMenu)
def handleHeaderMenu(self, pos):
print('column(%d)' % self.table.horizontalHeader().logicalIndexAt(pos))
menu = QtGui.QMenu()
menu.addAction('Add')
menu.addAction('Delete')
menu.exec_(QtGui.QCursor.pos())