I'm creating an app using Eric4 and PyQt4.
I have two dialog boxes, one runs as a thread and the other is a standard dialog box with a label inside, which I want to change to an image.
Every time the main window thread runs I want it to change the current image displayed in the dialog box to a new image. Everything works fine except every time the thread runs it creates a new dialog box with the new image inside - I want it to change the image in the dialog box that's currently open.
Dialog box with image inside:
class SubWindow(QDialog, Ui_subWindow):
def __init__(self, parent = None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
def main(self, img):
pic = self.imgView
pic.setPixmap(QtGui.QPixmap(os.getcwd() + img))
Thread which changes the image:
class MainWindow(QDialog, Ui_MainWindow, threading.Thread):
def __init__(self, parent = None):
threading.Thread.__init__(self)
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
#some code here which does some stuff then calls changeImg()
def changeImg(self):
img = SubWindow()
img.main(img)
I've not included all my code, only the relevant bits.
It looks like the problem is that you are creating a new SubWindow every time you wish to change the image. I would recommend creating the SubWindow as an attribute to MainWindow in the MainWindiw.__init__ function:
class MainWindow(QDialog, Ui_MainWindow, threading.Thread):
def __init__(self, parent = None):
threading.Thread.__init__(self)
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
self.img = SubWindow() # Create SubWindow once here
def changeImg(self):
self.img.main(self.img) # Only change the image, no new SubWindow
Related
I'm working on creating python plugin that implements image viewer and use layout to plased elements in correct plases. I want to resize all elements in dialog window of this plugin using resizeEvent of QDialog, but I have one strange problem: when I want to make dialog window smaller - all works good like on image1, but, if I want to make window bigger I have seen a problem like on image2:
Here is my resizeEvent method for my dialog:
def resizeEvent(self, a0: QResizeEvent):
geom = list(self.geometry().getCoords())
x_shift = geom[2] - geom[0] #transform x coord from monitor coords to dialog window coords
y_shift = geom[3] - geom[1] #transform y coord from monitor coords to dialog window coords
self.verticalLayout.setGeometry(QRect(0, 0, x_shift, y_shift))
And here is my code how I connect my ui with python code using uic:
import os
from qgis.PyQt import uic
from qgis.PyQt import QtWidgets
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'name_of_ui'))
class nameDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
super(status_checkerDialog, self).__init__(parent)
self.setupUi(self)
In this script, I create the resize function. Also, I would like to add that I use to build the skeleton of the module named Plugin Builder. Maybe this information will help you point out exactly where I am making a mistake. I also add the code skeleton that implements all functions of the module:
class status_checker:
def __init__(self, iface):
"Constructor"
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar"""
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI"""
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
def run(self):
"""Run method that performs all the real work"""
# Create the dialog with elements (after translation) and keep reference
# Only create GUI ONCE in callback, so that it will only load when the plugin is started
if self.first_start == True:
self.first_start = False #self.first_start is a variable that is created in the initialization function and initially set to true
self.dlg = status_checkerDialog()
I am trying to open a new window inside a mdiArea and I achieved it with the following code.
class Window(QMainWindow, MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_tool)
def open_tool(self):
# Create Sub Window
new_win = new_Window()
self.mdiArea.addSubWindow(new_win)
new_win.show()
self.mdiArea.cascadeSubWindows()
Now, since each new window that I open, has multiple long tasks, I wanted to run each new window in a new thread in order to prevent freezing of the entire gui.
I tried using the following code:
class Tool_Thread(QtCore.QThread):
def __init__(self, mdiArea):
# Get Widget Area
super().__init__()
self.mdiArea = mdiArea
# Create Sub Window
self.new_win = new_Window()
self.mdiArea.addSubWindow(self.new_win)
def run(self):
self.new_win.show()
and running it in the main gui with
class Window(QMainWindow, MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_tool)
def open_tool(self):
new_tool = TMTC_Thread(self.mdiArea)
new_tool .start()
but the main gui continues to freeze. Is there any way to handle cases like this?
I am trying to create a GUI (see attached screenshot) where it has about 6 sets of widgets where each set comprises of QLabel, QLineEdit and QPushButton.
Instead of writing the widgets and the layout again and again, I thought of writing up a wrapper function such that I will only need to write up 6 lines for the creation.
However, while this works efficiently for me in terms of the widgets creation, I realized that I am not able to set the Signal for the button(s) as I do not know the widget's names.
What will be the best way to set the signals if I decided to use this wrapper methodology?
The following is a screenshot of what I am trying to achieve as well as my code:
class MyDevTool(QtGui.QWidget):
def __init__(self, parent=None):
super(MyDevTool, self).__init__(parent)
self._create_ui()
def _create_hbox_layout(self, label):
h_layout = QtGui.QHBoxLayout()
label = QtGui.QLabel(label)
label.setFixedWidth(80)
line_edit = QtGui.QLineEdit()
push_btn = QtGui.QPushButton("<<<")
h_layout.addWidget(label)
h_layout.addWidget(line_edit)
h_layout.addWidget(push_btn)
return h_layout
def _create_ui(self):
main_layout = QtGui.QVBoxLayout()
main_layout.addLayout(
self._create_hbox_layout("Input Directory")
)
main_layout.addLayout(
self._create_hbox_layout("Output Directory")
)
self.setLayout(main_layout)
I have created two different pyqt windows, and within one of them, by pressing a button, it should bring up another smaller window. While my code does pretty much exactly what I just dais it should do, there is a problem with the way the smaller popup window is displayed.
This is my code for displaying the windows and the button functionality:
from PyQt4 import QtGui
from EnterprisePassport import Ui_StudentEnterprisePassport
from Session_tracker import Ui_Session_tracker
class StudentEnterprisePassport(Ui_StudentEnterprisePassport):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.sessionTracker_btn.clicked.connect(self.handleButton)
self.window2 = None
def handleButton(self):
if self.window2 is None:
self.window2 = Session_tracker(self)
self.window2.show()
class Session_tracker(Ui_Session_tracker):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = StudentEnterprisePassport()
window.show()
sys.exit(app.exec_())
I can still use the functions within the window, but I can't move it, or close it, and there is no title bar. Have I done something wrong within my code for the popup window to appear like this?
Edit:
Original Session tracker window: Original window
Popup session tracker window: Popup window
In order to show the other widget in it's own window, it has to be a QMainWindow or a QDialog.
One option, if you don't want to convert your existing Session_tracker to a QDialog, is to just wrap it in a QDialog
def handleButton(self):
if self.window2 is None:
self.window2 = QtGui.QDialog(self)
lay = QtGui.QVBoxLayout()
self.window2.setLayout(lay)
self.session_tracker = Session_tracker(self.window2)
lay.addWidget(self.session_tracker)
self.window2.show()
I have Qdialog with that I open from main window:
Dialog = myDialog(self)
Here is the code from new opened Dialog:
class myDialog(QtGui.QDialog, Ui_DialogCalibration):
def __init__(self, parent=None):
super(myDialog, self).__init__(parent)
self.setupUi(self)
How can pass parameter(lint) from main window to this new window, something like
Dialog = myDialog(self, listInformation)
and then in myDialog class use that list
class myDialog(QtGui.QDialog, Ui_DialogCalibration):
def __init__(self, parent=None, listInfo):
super(myDialog, self).__init__(parent)
self.listInfo = listInfo
self.setupUi(self)
Then, when you go to create the myDialog, you can add the list as a parameter. When you need to use it inside of your myDialog, you would access it as self.listInfo.
EDIT: To further expand on the comments:
If you have def __init__(self, parent=None, listInfo=None), you would call it as Dialog = myDialog(parent=self, listInfo=listInfo). If you had it as def __init__(self, parent, listInfo) you would do Dialog = myDialog(self, listInfo). Hopefully you see the pattern here.