i write some code in pyqt5 that create a table in main main:
class Ui_MainWindow(object):
def setupUi(self, MainWindow): ...
def retranslateUi(self, MainWindow):...
self.pushButton.setText(_translate("MainWindow", "print"))
self.pushButton.clicked.connect(self.printer)
def printer(self):...
and use this class by:
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
i wanna know how can i print from main page of my program?
This can be done rather easy using QPrinter class.
Below is well-commented example of how to do it.
import sys
from PyQt5 import QtGui, QtWidgets, QtPrintSupport
class App(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# Create some widgets
self.setGeometry(500, 500, 300, 300)
self.button = QtWidgets.QPushButton(
'Print QTextEdit widget (the one below)', self)
self.button.setGeometry(20, 20, 260, 30)
self.editor = QtWidgets.QTextEdit(
'Wow such text why not change me?', self)
self.editor.setGeometry(20, 60, 260, 200)
self.button.clicked.connect(self.print_widget)
def print_widget(self):
# Create printer
printer = QtPrintSupport.QPrinter()
# Create painter
painter = QtGui.QPainter()
# Start painter
painter.begin(printer)
# Grab a widget you want to print
screen = self.editor.grab()
# Draw grabbed pixmap
painter.drawPixmap(10, 10, screen)
# End painting
painter.end()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = App()
gui.show()
app.exec_()
To print whole window just replace screen = self.editor.grab() with screen = self.grab()
Related
How can I make QTextEdit save automatically when I'm done typing? I do not want it to be saved automatically when writing each letter separately. Rather, it is saved after all writing is completed only.
import sys
from PyQt5.QtWidgets import *
class MyMainWindow(QMainWindow):
def __init__(self):
super(MyMainWindow, self).__init__()
layout = QHBoxLayout()
centralWidget = QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
self.textedit = QTextEdit()
self.textedit.textChanged.connect(self.save_text)
layout.addWidget(self.textedit)
def save_text(self):
text=self.textedit.toPlainText()
with open('mytextfile.txt', 'w') as f:
f.write(text)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MyMainWindow()
form.show()
sys.exit(app.exec_())
The trick might be to create a button, once the button is pressed then save the text:
import sys
from PyQt5.QtWidgets import *
class MyMainWindow(QMainWindow):
def __init__(self):
super(MyMainWindow, self).__init__()
layout = QHBoxLayout()
centralWidget = QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
self.textedit = QTextEdit()
layout.addWidget(self.textedit)
self.pushbutton = QPushButton()
self.pushbutton.clicked.connect(self.save_text)
layout.addWidget(self.textedit)
def save_text(self):
text=self.textedit.toPlainText()
with open('mytextfile.txt', 'w') as f:
f.write(text)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = MyMainWindow()
form.show()
sys.exit(app.exec_())
Then once you done writing your text, just click the button and it will save your text.
I have a problem, i have made a QGraphicsView with 2 rectangles inside. I wanted them to resize when i resize the Dialog so i rewrite a dialog class. It works but at start i have the wrong sized rectangle
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsEllipseItem
import sys
# Redéfinition de dialog pour utiliser resize event
class MyDialog (QtWidgets.QDialog) :
def resizeEvent(self, event):
print("resize")
#print(view.sceneRect())
view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio) ######## I DONT KNOW WHY THIS LINE MAKE THE VIEW TOO SMALL AT START
QtWidgets.QDialog.resizeEvent(self, event)
#view.fitInView(rectangle)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(556, 580)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.graphicsView = QtWidgets.QGraphicsView(Dialog)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
global view
view = self.graphicsView
triangle = QtWidgets.QGraphicsRectItem(10,10,200,200)
rectangle = QtWidgets.QGraphicsRectItem(100,100,200,200)
global scene
scene = QtWidgets.QGraphicsScene()
scene.addItem(rectangle)
scene.addItem(triangle)
self.graphicsView.setScene(scene)
#self.graphicsView.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
#view.fitInView(scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
self.graphicsView_2 = QtWidgets.QGraphicsView(Dialog)
self.graphicsView_2.setObjectName("graphicsView_2")
self.verticalLayout.addWidget(self.graphicsView_2)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = MyDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
When i start the QDialog it looks like this
And when i resize the window it looks like i wanted it to look like
Note: It is recommended not to modify the code generated by Qt Designer, so for my answer to work you must regenerate the file using pyuic5: pyuic5 your_file.ui -o gui.py -x.
So that the fitInView method uses some property that is not updated until it makes the QGraphicsView visible, so the solution is to verify that it is visible:
main.py
from PyQt5 import QtCore, QtGui, QtWidgets
from gui import Ui_Dialog
class MyDialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
triangle = QtWidgets.QGraphicsRectItem(10, 10, 200, 200)
rectangle = QtWidgets.QGraphicsRectItem(100, 100, 200, 200)
scene = QtWidgets.QGraphicsScene()
scene.addItem(rectangle)
scene.addItem(triangle)
self.graphicsView.setScene(scene)
def resizeEvent(self, event):
if self.isVisible():
self.graphicsView.fitInView(
self.graphicsView.scene().sceneRect(), QtCore.Qt.KeepAspectRatio
)
super().resizeEvent(event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyDialog()
w.show()
sys.exit(app.exec_())
I am creating an application where I have a main window whit a label and then a docked widget that is in another file. I want to change the main windows label from a button at the docked widget. I try to import the main window file but then I can not access to the label. And I also tried to call a function in the main windows that changes the label but then the label does not change.
Here is the code:
main_window.py:
import results_window
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.define_main_windows()
self.create_dock_widgets()
def define_main_windows(self):
# Define de Main window properties
self.setMinimumSize(QSize(300, 100))
self.setWindowTitle("Python SkyLibris")
self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
self.setStyleSheet("QMainWindow {background: 'white';}")
self.top = 50
self.left = 0
self.width = 1300
self.height = 400
self.setGeometry(self.left, self.top, self.width, self.height)
self.result = QLabel("result:")
self.setCentralWidget(self.result)
def create_dock_widgets(self):
# Create dock widgets
self.results_window = results_window.results_window()
self.resultsWindowDock = QDockWidget("Results Viewer", self)
self.resultsWindowDock.setWidget(self.results_window )
self.resultsWindowDock.setFloating(False)
self.resultsWindowDock.setVisible(True)
self.addDockWidget(Qt.LeftDockWidgetArea, self.resultsWindowDock)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
results_window.py:
import main_window
class results_window(QWidget):
def __init__(self):
super(results_window, self).__init__()
print("init")
self.label = QLabel()
self.value = QLineEdit()
self.bt = QPushButton("Click")
self.bt.clicked.connect(self.clickMethod)
self.main_layout = QVBoxLayout()
self.main_layout.addWidget(self.label)
self.main_layout.addWidget(self.value)
self.main_layout.addWidget(self.bt)
self.setLayout(self.main_layout)
def clickMethod(self):
print(self.value.text())
text = self.value.text()
main_window.result.setText(text)
You are using the wrong tools, for example your code has a circular import that causes your application to close since it is equivalent to a while True.
In Qt, signals and slots are used to share data asynchronously, as well as contributing to the fact that there is no coupling between classes. In your case, Results_Window must have a signal that transmits that information to the MainWindow, this signal must be emit within clickMethod.
results_window.py
from PyQt5 import QtCore, QtWidgets
class Results_Window(QtWidgets.QWidget):
resultChanged = QtCore.pyqtSignal(str)
def __init__(self):
super(Results_Window, self).__init__()
print("init")
self.label = QtWidgets.QLabel()
self.value = QtWidgets.QLineEdit()
self.bt = QtWidgets.QPushButton("Click")
self.bt.clicked.connect(self.clickMethod)
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(self.label)
main_layout.addWidget(self.value)
main_layout.addWidget(self.bt)
#QtCore.pyqtSlot()
def clickMethod(self):
text = self.value.text()
self.resultChanged.emit(text)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = Results_Window()
w.show()
sys.exit(app.exec_())
main_window.py
from PyQt5 import QtCore, QtGui, QtWidgets
import results_window
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.define_main_windows()
self.create_dock_widgets()
def define_main_windows(self):
self.setMinimumSize(QtCore.QSize(300, 100))
self.setWindowTitle("Python SkyLibris")
self.setWindowIcon(QtGui.QIcon("skylibris_icon.png"))
self.setStyleSheet("QMainWindow {background: 'white';}")
top, left, width, height = 50, 0, 1300, 400
self.setGeometry(left, top, width, height)
self.result = QtWidgets.QLabel("result:")
self.setCentralWidget(self.result)
def create_dock_widgets(self):
self.results_window = results_window.Results_Window()
self.results_window.resultChanged.connect(self.result.setText)
self.resultsWindowDock = QtWidgets.QDockWidget("Results Viewer", self)
self.resultsWindowDock.setWidget(self.results_window )
self.resultsWindowDock.setFloating(False)
self.resultsWindowDock.setVisible(True)
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.resultsWindowDock)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
I had similar problem in PyQT5 where I was unable to access and set the local variables. After a lot of struggle I found writing to file and reading from file as the best solution. Simply write the desired output to file and access the same info from other file. Works great!
I have a simple progress bar that I want to pop up inside loops, like in the example below.
I have to instantiate it outside of the app, then adjust values for the loop. Why? I would've thought it'd be more ideal to instantiate a new progress bar class inside the MainWindow, but that doesn't show up. I assume it has to do with the app.exec. However, if I add a self.exec for the progress bar, it doesn't update, so what's the correct way of implementing it?
from PyQt5.Qt import *
import sys
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QWidget(MainWindow)
self.pushButton = QPushButton(self.centralwidget)
self.pushButton.setText("CLICK ME")
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton.clicked.connect(self.testloop)
def testloop(self):
n = 200
print(progressbar.wasCanceled())
progressbar.setMinimum(0)
progressbar.setValue(0)
progressbar.setMaximum(n)
progressbar.show()
for i in range(n):
progressbar.setValue(i)
if progressbar.wasCanceled(): # How can I un-cancel and reset the progress bar again?
break
class ProgressBar(QProgressDialog):
def __init__(self):
super().__init__()
self.setValue(0)
self.setModal(True)
def step(self, i):
self.setValue(i)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainwindow = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(mainwindow)
mainwindow.show()
progressbar = ProgressBar() # Do I need to instantiate a progressbar here,
# or can I instantiate and kill it inside the app code?
sys.exit(app.exec_())
Simple implementation of progress bar for a loop:
from PyQt5.Qt import *
import sys
import time
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QWidget(MainWindow)
self.pushButton = QPushButton(self.centralwidget)
self.pushButton.setText("CLICK ME")
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton.clicked.connect(self.testloop)
def testloop(self):
n = 10
progressbar = ProgressBar(n, title = "Copying files...")
for i in range(n):
time.sleep(0.01)
progressbar.setValue(i)
if progressbar.wasCanceled():
break
class ProgressBar(QProgressDialog):
def __init__(self, max, title):
super().__init__()
self.setMinimumDuration(0) # Sets how long the loop should last before progress bar is shown (in miliseconds)
self.setWindowTitle(title)
self.setModal(True)
self.setValue(0)
self.setMinimum(0)
self.setMaximum(max)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
mainwindow = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(mainwindow)
mainwindow.show()
sys.exit(app.exec_())
After a QDialog is shown using either show() or exec_() I need to add some additional widgets dynamically. How can I do this?
Just call show() on your widgets:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class testDialogs(QWidget):
def __init__(self, parent=None):
super(testDialogs, self).__init__(parent)
self.verticalLayout = QVBoxLayout(self)
self.pushButton = QPushButton(self)
self.pushButton.setText("Open a Dialog")
self.pushButton1 = QPushButton(self)
self.pushButton1.setText("Add a Text Edit")
self.plainTextEdit = QPlainTextEdit(self)
self.plainTextEdit.appendPlainText("This is a Widget")
self.verticalLayout.addWidget(self.pushButton)
self.verticalLayout.addWidget(self.pushButton1)
self.verticalLayout.addWidget(self.plainTextEdit)
self.pushButton.clicked.connect(self.on_pushButton_clicked)
self.pushButton1.clicked.connect(self.on_pushButton1_clicked)
#pyqtSlot()
def on_pushButton_clicked(self):
dialog = QDialog(self)
verticalLayout = QVBoxLayout(dialog)
plainTextEdit = QPlainTextEdit(dialog)
plainTextEdit.appendPlainText("This is a Dialog")
buttonBox = QDialogButtonBox(dialog)
buttonBox.setOrientation(Qt.Horizontal)
buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
buttonBox.setObjectName("buttonBox")
verticalLayout.addWidget(plainTextEdit)
verticalLayout.addWidget(buttonBox)
buttonBox.accepted.connect(dialog.close)
buttonBox.rejected.connect(dialog.close)
dialog.show()
#pyqtSlot()
def on_pushButton1_clicked(self):
plainTextEdit = QPlainTextEdit(self)
plainTextEdit.appendPlainText("This is another Text Edit")
self.verticalLayout.addWidget(plainTextEdit)
plainTextEdit.show()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
main = testDialogs()
main.show()
sys.exit(app.exec_())