How to set The push button should only work when two line edit input widgets contain text - python-3.x

I have created two line Edit input widgets and one push button.
I need to set The push button should only work when two line edits contain text.
I need to set two line edit input widgets as mandatory.

You can connect the QLineEdit.textEdited signal to a function to check if all the required fields contain text, and enable/disable the button accordingly. Here is an example:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Template(QWidget):
def __init__(self):
super().__init__()
self.f1 = QLineEdit()
self.f1.textEdited.connect(self.check_input)
self.f2 = QLineEdit()
self.f2.textEdited.connect(self.check_input)
self.btn = QPushButton('Enter')
self.btn.setDisabled(True)
form = QFormLayout(self)
form.addRow('Field 1', self.f1)
form.addRow('Field 2', self.f2)
form.addRow(self.btn)
def check_input(self):
if self.f1.text() and self.f2.text():
self.btn.setEnabled(True)
else:
self.btn.setDisabled(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = Template()
gui.show()
sys.exit(app.exec_())

Related

How to create contextmenu to delete row for inside of qtableview python

below is the code i am using:
How to create contextmenu to delete row for inside of qtableview python.
It is showing menu even i clicked on Qpushbutton also but i need to show the delete menu on only inside of qtableview. and let me know the way to delete the row of qtableview data.
Please let me know the solution.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import uic
import sys
import sqlite3
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
uic.loadUi("tableview.ui", self)
self.show()
self.view_msa()
self.pushButton.clicked.connect(self.view_msa)
def view_msa(self):
self.model = QtGui.QStandardItemModel(self)
self.tableView.setModel(self.model)
conn = sqlite3.connect('book.db')
cur = conn.cursor()
cur.execute("SELECT * FROM card")
db_data = cur.fetchall()
print(db_data)
for line in db_data:
row = []
for item in line:
cell = QStandardItem(str(item))
row.append(cell)
self.model.setHorizontalHeaderLabels(["Name","Age","Gender"])
self.model.appendRow(row)
def contextMenuEvent(self, event):
self.click_menu = QtWidgets.QMenu()
renameAction = QtWidgets.QAction('Delete', self)
renameAction.triggered.connect(lambda: self.renameSlot(event))
self.click_menu.addAction(renameAction)
self.click_menu.popup(QtGui.QCursor.pos())
def renameSlot(self, event):
print("Renameing slot called")
app = QApplication(sys.argv)
window = UI()
app.exec_()
All widget have the contextMenuPolicy property, which if set to QtCore.Qt.CustomContextMenu allows to connect to the customContextMenuRequested(pos) signal (note that the pos is in widget coordinates). From there you can access the index that is at the mouse position through indexAt or, better, get the selectedIndexes (which is useful if you have multiple selection enabled).
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
# ...
self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tableView.customContextMenuRequested.connect(self.tableMenu)
def tableMenu(self, pos):
selected = self.tableView.selectedIndexes()
if not selected:
return
menu = QtWidgets.QMenu()
deleteAction = menu.addAction('Delete rows')
deleteAction.triggered.connect(lambda: self.removeRows(selected))
menu.exec_(QtGui.QCursor.pos())
def removeRows(self, indexes):
# get unique row numbers
rows = set(index.row() for index in indexes)
# remove rows in *REVERSE* order!
for row in sorted(rows, reverse=True):
self.model.removeRow(row)
Note that in this case you have to use menu.exec() (which is usually the preferred method), not popup(), otherwise the function will return instantly and the menu won't probably shown up because of internal processing of the mouse events: exec blocks until it returns (whether any of its actions are triggered or it's closed), popup returns immediately.

slot to right click menu action does does not work

I have written the below code to which I finally managed to add menu but connecitn menu to a function doesnt seem to work:
import os
from PyQt5 import uic
from PyQt5 import QtWidgets
from PyQt5 import QtCore
FILE_LOCATION = os.path.dirname(os.path.realpath(__file__))
class MainDialogWindow(QtWidgets.QDialog):
def __init__(self):
super(MainDialogWindow,self).__init__()
ui_file = os.path.join(FILE_LOCATION, "example.ui")
self._ui = uic.loadUi(ui_file, self)
self.registerCallbacks()
self.initUI()
def initUI(self):
"""Initialize the UI.
"""
self.textBrowser.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
def registerCallbacks(self):
self.textBrowser.customContextMenuRequested.connect(self.context_menu)
# self.connect(self.textBrowser, QtCore.Signal('customContextMenuRequested(const QPoint &)'), self.context_menu)
def context_menu(self, pos):
menu = QtWidgets.QMenu(self)
action = menu.addAction("clear")
menu.exec_(self.mapToGlobal(pos))
action.trigered.connect(self.clear)
def clear(self):
"""Slot to claer text.
"""
print("clear")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainDialogWindow()
window.show()
window.setGeometry(500, 300, 300, 300)
sys.exit(app.exec_())
please helpp,, I want call the clear function from the right click menu
I don't seem to understand how the menu.exec_() method works, that method blocks the execution of sequential tasks until the user selects a QAction from the QMenu. In your case, for example, until when you press "clear" and the triggered signal is emitted (note: you have a typo), but at that moment there is no connection, so the clear method will not be called. The solution is to make the connection before invoking the QMenu exec_():
def context_menu(self, pos):
menu = QtWidgets.QMenu(self)
action = menu.addAction("clear")
action.triggered.connect(self.clear)
menu.exec_(self.mapToGlobal(pos))

How to connect in realtime two QCombobox

I working on the PyQt5 ui framework. How to connect in realtime two QCombobox so that the QCombobox 2 shall load a data based on the text in QCombobox1.
Here is a very small example. The items in the second combo box are changed by connecting a slot to the textChanged signal of the first combobox. I use a dictionary to look up which items should be displayed in the second combo box depending on the current text in the first combobox.
from PyQt5.QtWidgets import QWidget, QApplication, QComboBox, QFormLayout
class Widget(QWidget):
def __init__(self, parent = None):
super().__init__(parent)
self.categories = {'animals':['cat', 'dog', 'parrot', 'fish'],
'flowers':['daisies', 'tulips', 'daffodils', 'roses'],
'colors':['red', 'orange', 'blue', 'purple']}
self.cat_combobox = QComboBox(self)
self.item_combobox = QComboBox(self)
self.cat_combobox.setEditable(False)
self.item_combobox.setEditable(False)
self.cat_combobox.currentTextChanged.connect(self.set_category)
self.cat_combobox.addItems(sorted(self.categories.keys()))
form_layout = QFormLayout(self)
form_layout.addRow('Category', self.cat_combobox)
form_layout.addRow('Items', self.item_combobox)
def set_category(self, text):
self.item_combobox.clear()
self.item_combobox.addItems(self.categories.get(text, []))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Widget()
window.show()
app.exec()

print current selected file name

I am using the following function to set the text of a Label to be the file name
i just picked , but i want to get the name of the file i'm currently selecting before canceling or opening the file from the dialog
is there any way to do so by using tkinter or any other framework/lib
here's the code
def pick_csv(self):
filename = filedialog.askopenfilename()
filelabel.config(text=filename)
#filelabel should get the name of the selected file
#before closing the dialog
I don't think you can use the native askopenfilename to achieve this. But you can write your own class that inherit from FileDialog. It will look ugly and needs some work on the layout.
from tkinter import *
from tkinter import filedialog
import os
root = Tk()
a = Label(root,text="Waiting for selection")
a.pack()
class CustomDialog(filedialog.FileDialog):
def __init__(self,master,path=""):
filedialog.FileDialog.__init__(self,master)
self.files.bind("<Button-1>",self.set_label)
self.selected = None
self.go(path)
def set_label(self,*args):
a.config(text=self.files.get(self.files.curselection()))
self.selected = os.path.join(self.directory, self.files.get(self.files.curselection()))
def cancel_command(self, event=None):
self.selected = None
self.quit()
def click():
f = CustomDialog(root)
if f.selected:
print (f.selected)
b = Button(root,text="Browse",command=click)
b.pack()
root.mainloop()

How to see signals from QWidgets inside dynamically created QTabWidget pages?

EDIT : I've come up with a solution, and it's much more straightforward than I thought. Original code and question at the top. My solution after "The Question" below..
The Example
from PyQt4 import QtGui, QtCore
from example_Ui import Ui_MainWindow
from filler_Ui import Form
class TabFiller(Form):
def __init__(self, parent=None):
Form.__init__(self, parent)
def TabButtonClicked(self):
print("Tab button pressed.")
def LineEditChanged(self):
print("LineEdit contents edited in tab page!")
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
tab_filler = [] # create empty list for tab contents
tab_page = [] # create empty list for tab page
tab_count = 0
def CreateNewTab(self):
tab_title = "New Tab : " + str(self.tab_count)
self.tab_filler.append(TabFiller())
self.tab_filler[self.tab_count].label.setText(tab_title)
self.tab_page.append(self.tab_filler[self.tab_count])
self.tabWidget.addTab(self.tab_page[self.tab_count], tab_title)
self.tab_count += 1
def MainButtonPressed(self):
self.CreateNewTab()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
MainWindow contains a QTabWidget, which is a Button. clicked() signal has been defined in QtDesigner to be sent to the MainButtonPressed() function inside the MainWindow class.
Form widget also created in QTdesigner. Used to fill additional Tab Pages.
This contains a Button widget, and a LineEdit Widget.
The Question
I can't get my head around how I can tell which widget has been clicked or edited in each tab.
I know that each Tab Page is stored in the list called tab_page.
Within the MainWindow class, how would I receive a clicked() or finishedEditing() signal for a given widget in a currently active tab?
A Solution
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtGui
from example_Ui import Ui_MainWindow
from filler_Ui import Form
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
tab_index = 1 # 1 because we already made a default tab in QtDesigner
def LineEditChanged(self):
findWidget = self.tabWidget.widget(self.tabWidget.currentIndex()).findChildren(QtGui.QLineEdit, "lineEdit")
if findWidget[0].isModified() == True:
print("LineEdit contents edited in tab page!")
print("Name of page edited :", "'", self.tabWidget.tabText(self.tabWidget.currentIndex()),"'")
def TabButtonPressed(self):
print("YOU DID IT!")
print("Current Tab Index = ", self.tabWidget.currentIndex())
def CreateNewTab(self, tabNum):
tab_title = "New Tab : " + str(self.tab_index)
self.tabWidget.addTab(Form(), tab_title)
def MainButtonPressed(self):
self.CreateNewTab(self.tab_index)
findWidget = self.tabWidget.widget(self.tab_index).findChildren(QtGui.QPushButton, "tabButton")
findWidget[0].clicked.connect(self.TabButtonPressed)
findWidget = self.tabWidget.widget(self.tab_index).findChildren(QtGui.QLineEdit, "lineEdit")
findWidget[0].editingFinished.connect(self.LineEditChanged)
self.tab_index += 1
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Using this there's no need for storing each tab page object in a list. You basically use the QTabWidget to index your pages, and off you go.
If anyone has a more elegant way than this, please inform ;)
As outlined in my edited question, I did find the solution to this, which is to use the QTabWidget to "index" each dynamically created tab page.
In QtDesigner I created a main window with one QTabWidget and one button thusly;
Here's the object tree for that;
NOTE: I added a signal/slot for the "Click Me!" button in QtDesigner, so that when that button is clicked, the MainButtonPressed function is called.
To fill the tab pages, I also created a Form in QtDesigner, with a button and a QLineEdit widget;
And the object tree for that;
I'll reproduce the code here. NOTE: I've now updated this answer to use findChild rather than findChildren above:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtGui
from example_Ui import Ui_MainWindow
from filler_Ui import Form
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
tab_index = 1 # 1 because we already made a default tab in QtDesigner
def LineEditChanged(self):
findWidget = self.tabWidget.widget(self.tabWidget.currentIndex()).findChild(QtGui.QLineEdit, "lineEdit")
if findWidget.isModified() == True:
print("LineEdit contents edited in tab page!")
print("Name of page edited :", "'", self.tabWidget.tabText(self.tabWidget.currentIndex()),"'")
def TabButtonPressed(self):
print("YOU DID IT!")
print("Current Tab Index = ", self.tabWidget.currentIndex())
def CreateNewTab(self, tabNum):
tab_title = "New Tab : " + str(self.tab_index)
self.tabWidget.addTab(Form(), tab_title)
def MainButtonPressed(self):
self.CreateNewTab(self.tab_index)
findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QPushButton, "tabButton")
findWidget.clicked.connect(self.TabButtonPressed)
findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QLineEdit, "lineEdit")
findWidget.editingFinished.connect(self.LineEditChanged)
self.tab_index += 1
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
When run, pressing the "Click Me!" button on the main tab page creates a new tab, and adds the contents of the "filler" page to it.
The variable tab_index keeps track of how many tabs there are and allows you to reference the contents of each tab.
To find a widget in a tab, you use the findChild function of Qt;
findWidget = self.tabWidget.widget(self.tab_index).findChild(QtGui.QPushButton, "tabButton")
Finding a specific widget is straightforward. You specify the type of widget you're looking for (QtGui.QPushButton) , and the name you assigned it in QtDesigner (tabButton)
In this case the found widget can be referenced by the variable findWidget.
You can then connect signals to function slots as usual;
findWidget.clicked.connect(self.TabButtonPressed)
In this case I used the new-style signal connection method to connect the clicked() signal to a function named TabButtonPressed in my program.
Rinse and repeat for each widget on the Tab Page you wish to do something with.
After that, it really is plain sailing ;)
I hope this information helps others in their GUI endeavours. You can probably use the same technique with the QToolBox widget.

Resources