PyQt5) I'm Try to open QFileDialog on the main window but QFileDialog skips the main window - pyqt5

I'm trying to open QFileDialog widget when I click the push button on the main window.
but after I run the code QfileDialog widget is opened without main window widget.
Below is my code :
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
import sys
class Python_Install(QtWidgets.QWidget) :
def __init__(self):
super().__init__()
self.setWindowTitle('main_window')
self.resize(800, 600)
self.initUI()
def initUI(self):
# add GroupBox
self.gb = QtWidgets.QGroupBox(self)
self.gb.setGeometry(QtCore.QRect(40, 120, 731, 331))
self.gb.setTitle('Select File')
# LB_host + LE1(LineEdit) + FC1(File Choose)
self.LB_host = QtWidgets.QLabel(self.gb)
self.LB_host.setGeometry(QtCore.QRect(50, 70, 121, 18))
self.LB_host.setText('host file :')
self.LE1 = QtWidgets.QLineEdit(self.gb)
self.LE1.setGeometry(QtCore.QRect(200, 60, 301, 25))
self.LE1.setReadOnly(True)
self.FC1 = QtWidgets.QPushButton(self.gb)
self.FC1.setGeometry(QtCore.QRect(510, 60, 112, 34))
self.FC1.clicked.connect(self.File_Choose(self.LE1))
def File_Choose(self, X):
file, check = QtWidgets.QFileDialog.getOpenFileName(self, 'Select File', "", "All Files (*);;Text Files (*.txt)")
if check:
X.setText(file)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mw = Python_Install()
mw.show()
sys.exit(app.exec_())
I think this part of the code is wrong...
self.FC1.clicked.connect(self.File_Choose(self.LE1))
def File_Choose(self, X):
file, check = QtWidgets.QFileDialog.getOpenFileName(self, 'Select File', "", "All Files (*);;Text Files (*.txt)")
if check:
X.setText(file)
Because If I change that part as below, It works as I indented :
self.FC1.clicked.connect(self.File_Choose)
def File_Choose(self):
file, check = QtWidgets.QFileDialog.getOpenFileName(self, 'Select File', "", "All Files (*);;Text Files (*.txt)")
if check:
self.LE1.setText(file)
But... what I want is passing the QLineEdit object to 'File_Choose' slot when 'push button' clicked event occurs and writing the chosen file name to the QLineEdit object.
how could I fix it...?

Related

PyQt5) When I try to open Second window, it is closed without any error messages

I'm trying to open second window on main window.
I made 2 classes for each windows, and run the code. when I click the button on main window, the main window is closed and second windows show. but after 1 seconds the second window is closed and the process ends.
Really I don't know why it does...
from PyQt5 import QtWidgets
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(400, 300)
# Button
self.button = QtWidgets.QPushButton(self)
self.button.setGeometry(0, 0, 400, 300)
self.button.setText('Open Sub Window')
self.button.setStyleSheet('font-size:40px')
self.button.clicked.connect(self.sub_show)
def sub_show(self):
self.hide()
self.sub_window = SubWindow()
self.sub_window.exec()
self.show()
class SubWindow(QtWidgets.QWidget):
def __init__(self):
super(SubWindow, self).__init__()
self.resize(400, 300)
self.button2 = QtWidgets.QPushButton(self)
self.button2.setGeometry(0, 0, 400, 300)
self.button2.setText('Back to Main window')
self.button2.setStyleSheet('font-size:40px')
self.button2.clicked.connect(self.home)
self.show()
def home(self):
self.close()
if __name__ == "__main__" :
app = QtWidgets.QApplication([])
mw = MainWindow()
mw.show()
sys.exit(app.exec())
You are calling show a few to many times. Also QWidget doesn't have an exec method. You will also want the first window to reappear when you close the second I assume.
I made some changes in the example below. Give it a try:
from PyQt5 import QtWidgets
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(400, 300)
self.button = QtWidgets.QPushButton(self)
self.button.setGeometry(0, 0, 400, 300)
self.button.setText('Open Sub Window')
self.button.setStyleSheet('font-size:40px')
self.button.clicked.connect(self.sub_show)
def sub_show(self):
self.hide()
self.sub_window = SubWindow()
# connect signal to show again when button2 is pressed
self.sub_window.button2.clicked.connect(self.show)
self.sub_window.show()
class SubWindow(QtWidgets.QWidget):
def __init__(self):
super(SubWindow, self).__init__()
self.resize(400, 300)
self.button2 = QtWidgets.QPushButton(self)
self.button2.setGeometry(0, 0, 400, 300)
self.button2.setText('Back to Main window')
self.button2.setStyleSheet('font-size:40px')
self.button2.clicked.connect(self.close)
if __name__ == "__main__" :
app = QtWidgets.QApplication([])
mw = MainWindow()
mw.show()
sys.exit(app.exec())

PyQt5 input text can't be executed as code in QPlainTextEdit

I have a QMainWindow which contains a QPlainTextEdit and a button with clicked even connected. When user finishes text input and press the button, I just want to execute user input for example "1+1". I should get "2", but it is "1+1". Very appreciated for your reply, thanks!
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, \
QApplication, QVBoxLayout, QPlainTextEdit, QWidget
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setFixedSize(600, 600)
l_layout = QVBoxLayout()
self.edit = QPlainTextEdit()
self.edit.setFixedSize(400, 300)
self.edit1 = QPlainTextEdit()
self.edit1.setFixedSize(100, 100)
self.btn = QPushButton('Test')
self.btn.clicked.connect(self.press)
l_layout.addWidget(self.edit)
l_layout.addWidget(self.edit1)
l_layout.addWidget(self.btn)
dummy_widget = QWidget()
dummy_widget.setLayout(l_layout)
self.setCentralWidget(dummy_widget)
def press(self):
text = self.edit.toPlainText()
try:
code = """print(text)"""
exec(code)
except Exception as e:
print('not ok!')
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
You should evaluate the input text and then print it, like so:
def press(self):
text = self.edit.toPlainText()
try:
print(eval(text))
except Exception as e:
print('not ok!')
Pay attention, because eval() use can lead to security issues (people executing python code on your app). Make sure your input is sanitized.

QMdiArea shows incorrectly [duplicate]

This question already has answers here:
QMdiArea not adding subwindow
(2 answers)
Closed 1 year ago.
I have a problem when using QMdiArea in PyQt5, the following is what I have done:
I create a demo UI with Qt designer, looks like:
When I preview it in Qt designer, it looks OK:
However, when I use pyqt5_uic to convert the .ui file to .py file, and run the code, it looks like this:
I found that the corresponding .py code generate with uic tools fails to set parent for subwindows in mdiarea:
self.mdiArea = QtWidgets.QMdiArea(IOWidgets)
self.mdiArea.setGeometry(QtCore.QRect(555, 120, 421, 181))
self.mdiArea.setObjectName("mdiArea")
self.subwindow = QtWidgets.QWidget()
self.subwindow.setObjectName("subwindow")
self.lineEdit_1_IO = QtWidgets.QLineEdit(self.subwindow)
self.lineEdit_1_IO.setGeometry(QtCore.QRect(20, 20, 61, 21))
self.lineEdit_1_IO.setObjectName("lineEdit_1_IO")
self.spinBox_1_IO = QtWidgets.QSpinBox(self.subwindow)
self.spinBox_1_IO.setGeometry(QtCore.QRect(30, 60, 42, 22))
self.spinBox_1_IO.setObjectName("spinBox_1_IO")
if I change the critical line code to:
self.subwindow = QtWidgets.QWidget(self.mdiArea)
then I can see the subwindow in mdiarea, but it looks strange:
here is simple demo:
the .py code generate with uic tools is Ui_Mdi_simple.py:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MDI_test(object):
def setupUi(self, MDI_test):
MDI_test.setObjectName("MDI_test")
MDI_test.resize(545, 336)
self.mdiArea = QtWidgets.QMdiArea(MDI_test)
self.mdiArea.setGeometry(QtCore.QRect(70, 50, 331, 221))
self.mdiArea.setObjectName("mdiArea")
self.subwindow = QtWidgets.QWidget()
self.subwindow.setObjectName("subwindow")
self.comboBox = QtWidgets.QComboBox(self.subwindow)
self.comboBox.setGeometry(QtCore.QRect(50, 30, 68, 22))
self.comboBox.setObjectName("comboBox")
self.lineEdit = QtWidgets.QLineEdit(self.subwindow)
self.lineEdit.setGeometry(QtCore.QRect(50, 70, 113, 20))
self.lineEdit.setObjectName("lineEdit")
self.radioButton = QtWidgets.QRadioButton(self.subwindow)
self.radioButton.setGeometry(QtCore.QRect(50, 110, 95, 20))
self.radioButton.setObjectName("radioButton")
self.subwindow_2 = QtWidgets.QWidget()
self.subwindow_2.setObjectName("subwindow_2")
self.retranslateUi(MDI_test)
QtCore.QMetaObject.connectSlotsByName(MDI_test)
def retranslateUi(self, MDI_test):
_translate = QtCore.QCoreApplication.translate
MDI_test.setWindowTitle(_translate("MDI_test", "Form"))
self.subwindow.setWindowTitle(_translate("MDI_test", "subwindow_1"))
self.radioButton.setText(_translate("MDI_test", "RadioButton"))
self.subwindow_2.setWindowTitle(_translate("MDI_test", "subwindow_2"))
the main code is:
import sys
from PyQt5.QtWidgets import QWidget, QApplication
from Ui_Mdi_simple import Ui_MDI_test
class MDI_demo(QWidget, Ui_MDI_test):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MDI_demo()
win.show()
sys.exit(app.exec_())
the results turns out to be:
I found adding the following two lines of codes in Ui_MDI_test solves the problem:
self.mdiArea.addSubWindow(self.subwindow)
self.mdiArea.addSubWindow(self.subwindow_2)
# eyllanesc, thanks.

How can I add Icons to a QListWidget

I have a program that has you drag and drop files into a QListWidget box and then you click a button to upload those files to a bucket. I would like to say which files have been uploaded and which one is currently being uploaded with an icon. Is there a way to add Icons inside/next to the QListWidget box?
Here is some of the code for the QListWidget and the drag and drop feature. I am just hoping there is a way to add icons
import sys, os
from PyQt5.QtWidgets import QApplication, QMainWindow, QListWidget, QListWidgetItem, QPushButton
from PyQt5.QtCore import Qt, QUrl
class ListBoxWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAcceptDrops(True)
self.resize(600, 600)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
links = []
for url in event.mimeData().urls():
# https://doc.qt.io/qt-5/qurl.html
if url.isLocalFile():
links.append(str(url.toLocalFile()))
else:
links.append(str(url.toString()))
self.addItems(links)
else:
event.ignore()
class AppDemo(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1200, 600)
self.listbox_view = ListBoxWidget(self)
self.btn = QPushButton('Get Value', self)
self.btn.setGeometry(850, 400, 200, 50)
self.btn.clicked.connect(lambda: print(self.getSelectedItem()))
def getSelectedItem(self):
item = QListWidgetItem(self.listbox_view.currentItem())
return item.text()
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = AppDemo()
demo.show()
sys.exit(app.exec_())
I have tried adding QIcon to the self.addItems(links) line but it continues to give me an error about arguments.
Instead of adding items using addItems, create indivual QListWidgetItems and add them one by one using addItem(QListWidgetItem).
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
for url in event.mimeData().urls():
# https://doc.qt.io/qt-5/qurl.html
if url.isLocalFile():
address = str(url.toLocalFile())
icon = QIcon('localIcon.png')
else:
address = str(url.toString())
icon = QIcon('remoteIcon.png')
self.addItem(QListWidgetItem(icon, address))
If you want to change the icon of an existing item, access it using item() and use setIcon():
def setIconForItem(self, row, icon):
self.listbox_view.item(row).setIcon(icon)

Open PyQt5 save file dialog from jupyter notebook to save matplotlib figure

What I want to do
I am trying to make an interactive plot for a Jupyter Notebook. The functions are all written in different files, but their intended use is in interactive notebook sessions. I have a Button widget on a matplotlib figure, which, when clicked, I want to open a file dialog where a user can enter a filename to save the figure to. I am on Mac OSX (Mojave 10.14.6) and Tkinter is giving me major problems (complete system crashes), so I am trying to implement this with PyQt5.
The code
-----------
plotting.py
-----------
from . import file_dialog as fdo
import matplotlib.pyplot as plt
import matplotlib.widgets as wdgts
def plot_stack(stack):
fig, ax = plt.subplots(figsize=(8, 6))
plt.subplots_adjust(bottom=0.25, left=-0.1)
... # plotting happens here
# button for saving
def dosaveframe(event):
fname = fdo.save()
fig.savefig(fname) # to be changed to something more appropriate
savea = plt.axes([0.65, 0.8, 0.15, 0.05], facecolor=axcolor)
saveb = Button(savea, "save frame", hovercolor="yellow")
saveb.on_clicked(dosaveframe)
savea._button = saveb # for persistence
plt.show()
--------------
file_dialog.py
--------------
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import (QWidget, QFileDialog)
class SaveFileDialog(QWidget):
def __init__(self, text="Save file", types="All Files (*)"):
super().__init__()
self.title = text
self.setWindowTitle(self.title)
self.types = types
self.filename = self.saveFileDialog()
self.show()
def saveFileDialog(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
filename, _ = (
QFileDialog.getSaveFileName(self, "Enter filename",
self.types, options=options))
return filename
def save(directory='./', filters="All files (*)"):
"""Open a save file dialog"""
app = QApplication([directory])
ex = SaveFileDialog(types=filters)
return ex.filename
sys.exit(app.exec_())
What is not working
The save dialog opens and it responds to the mouse, but not to the keyboard. The keyboard stays connected to the notebook no matter if I select the little window, so when I press "s" it saves the notebook. As such, the user can not enter a file path. How can I make this work? I have Anaconda, PyQt 5.9.2, matplotlib 3.1.1, jupyter 1.0.0.
I found a very crappy, non-clean solution but it seems to work. For some reason, opening a QFileDialog directly does not allow me to activate it. It opens up behind the active window from where it was called (terminal window or browser in Jupyter Notebook) and does not respond to the keyboard. So the save function in the following block does NOT work as expected on Mac:
from PyQt5.QtWidgets import QApplication, QFileDialog
def save(directory='./', filters="All files (*)"):
app = QApplication([directory])
path, _ = QFileDialog.getSaveFileName(caption="Save to file",
filter=filters,
options=options)
return path
What does work is if the file dialog is opened from a widget. So working with a dummy widget that never shows up on the screen does work for me, at least from the command line:
from PyQt5.QtWidgets import (QApplication, QFileDialog, QWidget)
class DummySaveFileDialogWidget(QWidget):
def __init__(self, title="Save file", filters="All Files (*)"):
super().__init__()
self.title = title
self.filters = filters
self.fname = self.savefiledialog()
def savefiledialog(self):
filename, _ = QFileDialog.getSaveFileName(caption=self.title,
filter=self.filters,
options=options)
return filename
def save(directory='./', filters="All files (*)"):
app = QApplication([directory])
form = DummySaveFileDialogWidget()
return form.fname
If anyone finds a more elegant solution that works let me know
EDIT: this works when it is called from the command line, but still not from a Jupyter Notebook. Also tried this, no success. The file dialog stays behind the browser window and does not respond to the keyboard.