问题
I have a QTableWidget
with which I would like to update from a QLinEdit
embedded into a context menu. Now, in the QLinEdit
a server name is entered, when the key is pressed the program scans MySQL database to see if the server name is in it, if it is, it updates the QTableWidget
with the data from the server name table, if it is not found, it gives an error messageBox
.
What I can not do is connect the context menu QLinEdit
to update the QTableWidget
.
connecting QTableWidget
to context menu:
self.table1.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.table1.customContextMenuRequested.connect(self.handleHeaderMenu)
contextmenu:
def handleHeaderMenu(self, pos):
self.custom_choice = QtGui.QLineEdit()
self.menu = QtGui.QMenu()
self.custom_choice.setPlaceholderText("Server")
self.wac = QtGui.QWidgetAction(self.menu)
self.wac.setDefaultWidget(self.custom_choice)
self.menu.setStyleSheet("QMenu::item {background-color: #264F7D;color: white; font-weight:bold;}")
self.menu.addAction("Choose Server to Monitor:")
self.menu.addSeparator()
self.actionJuliet = self.menu.addAction('Juliet')
self.actionJulietleft = self.menu.addAction('JulietLeft')
self.actionPong = self.menu.addAction('Pong')
self.actionHulk = self.menu.addAction('Hulk')
self.actionCustom = self.menu.addAction(self.wac)
action = self.menu.exec_(QtGui.QCursor.pos())
self.connect(self.custom_choice, QtCore.SIGNAL("returnPressed()"),self.refreshdata)
Data fetcher/scanner:
def get_data(self):
self.tx = self.custom_choice.text()
self.model.execute("show TABLES;")
table_array = []
table_names = self.model.fetchall()
for lines in table_names:
lines = str(lines)
lines = lines.strip("()""''"",")
table_array.append(lines)
if any("%s" % self.tx in s for s in table_array):
table_name = self.tx
self.model.execute("""SELECT computer_name
FROM %s""" % (table_name))
new_user_name = self.model.fetchall()
print new_user_name,table_name
self.model.execute("""SELECT idle_time
FROM %s""" % (table_name))
new_idle = self.model.fetchall()
self.model.execute("""SELECT files_opened
FROM %s""" % (table_name))
new_files = self.model.fetchall()
self.model.execute("""SELECT active_time
FROM %s""" % (table_name))
new_active = self.model.fetchall()
self.model.execute("""SELECT session_type
FROM %s""" % (table_name))
new_session = self.model.fetchall()
self.model.execute("""SELECT cpu
FROM %s""" % (table_name))
new_cpu_load = self.model.fetchall()
self.model.execute("""SELECT avg_disk_queue
FROM %s""" % (table_name))
new_disk_queue_load = self.model.fetchall()
new_data_user = [item0[0] for item0 in new_user_name]
new_data_idle = [item1[0] for item1 in new_idle]
new_data_files = [item2[0] for item2 in new_files]
new_data_active = [item3[0] for item3 in new_active]
new_data_session = [item4[0] for item4 in new_session]
new_data_cpu_load = [item5[0] for item5 in new_cpu_load]
new_data_disk_queue_load = [item6[0] for item6 in new_disk_queue_load]
self.lista = new_data_user
self.listb = new_data_disk_queue_load
self.listc = new_data_cpu_load
self.listd = new_data_active
self.liste = new_data_files
self.listf = new_data_session
self.listg = new_data_idle
self.mystruct2 = {'A':self.lista, 'B':self.listb, 'C':self.listc,'E':self.liste,'D':self.listd,'F':self.listf,'G':self.listg}
回答1:
The design of your handleHeaderMenu
is a bit off. One of the main issues with the way it is currently structured is that you connect a signal to the QLineEdit
after the popup menu has already finished. So you would miss that signal.
action = self.menu.exec_(QtGui.QCursor.pos())
self.connect(self.custom_choice,
QtCore.SIGNAL("returnPressed()"),
self.refreshdata)
QMenu.exec_()
is a blocking call. It starts the event loop for the menu and waits for it to finish. Once it closes and returns the QAction that was selected, you then make a connection. I will get into a correction for this after my next point...
The menu you are building from scratch each time doesn't have to be saved to member attributes and used externally. There are two ways to go about doing a custom popup menu. If its primarily static, then you can build it once in your class init, or make it it's own class, and then just reuse the instance. Or in your case, you could build it up each time which is fine. But instead of relying on persistant references to the components of the menu and using a signal, why not just build it temporarily, and explicitly handle the results?
def handleHeaderMenu(self, pos):
menu = QtGui.QMenu()
menu.setStyleSheet("""
QMenu::item {
background-color: #264F7D;
color: white;
font-weight:bold;}
""")
text = menu.addAction("Choose Server to Monitor:")
text.setEnabled(False)
menu.addSeparator()
actionJuliet = menu.addAction('Juliet')
actionJulietleft = menu.addAction('JulietLeft')
actionPong = menu.addAction('Pong')
actionHulk = menu.addAction('Hulk')
wac = QtGui.QWidgetAction(menu)
custom_choice = QtGui.QLineEdit()
custom_choice.setPlaceholderText("Server")
wac.setDefaultWidget(custom_choice)
menu.addAction(wac)
menu.setActiveAction(wac)
custom_choice.returnPressed.connect(wac.trigger)
action = menu.exec_(QtGui.QCursor.pos())
if action:
if action == wac:
self.tx = str(custom_choice.text()).strip()
else:
self.tx = str(action.text())
self.refreshdata()
def refreshdata(self):
print self.tx
Here we just create a bunch of temp widgets for the menu that will get garbage collected. After showing the menu, we check the returned action and then manually set our table attribute, and call refresh. Also, we needed to set the signal from the custom QLineEdit
to trigger its widget action internally.
Lastly, is it really necessary to do 8 sql queries and a whole bunch of data reorganizing every time you want to load this data? This could be highly simplified:
def get_data(self):
table_check = """
SELECT table_name FROM information_schema.tables
WHERE table_schema = %s AND table_name = %s
"""
table_name = self.tx
count = self.model.execute(table_check, (self.theDatabaseName, table_name))
if not count:
# warn the user that the table name does not exist
warn_user_of_bad_table()
return
sql = """
SELECT
computer_name, idle_time, files_opened,
active_time, session_type, cpu, avg_disk_queue
FROM %s
""" % table_name
count = self.model.execute(sql)
if not count:
warn_database_error()
return
results = self.model.fetchall()
user, idle , files, active, session, cpu, disk = zip(*results)
self.lista = user
self.listb = disk
self.listc = cpu
self.listd = active
self.liste = files
self.listf = session
self.listg = idle
self.mystruct2 = {
'A' : self.lista,
'B' : self.listb,
'C' : self.listc,
'E' : self.liste,
'D' : self.listd,
'F' : self.listf,
'G' : self.listg
}
You only need two queries here. The first really simple one to check if the table exists, by using the scheme, instead of parsing through a big SHOW TABLES output. And the second which gets all your data in one query (as a bunch of rows, and then uses zip
to regroup them into columns.
来源:https://stackoverflow.com/questions/11959555/updating-a-qtablewidget-from-contextmenu-linedit-pyqt