我的代码如下:
medi_colab.db的提取代码:
from collections import OrderedDict
import pandas as pd
import numpy as np
import sqlite3
pd.set_option('display.max_columns', 5)
df = pd.read_csv('icd_codes_final.csv')
#print(df[['icd_code', 'common_name']].head(20))
#generate unique icd codes and the common names associated with them
#convert to lists
icd_codes = df['icd_code'].values.tolist()
common_names = df['common_name'].values.tolist()
#Remove duplicates while preserving order
icd_codes = list(sorted(OrderedDict.fromkeys(icd_codes)))
common_names = list(OrderedDict.fromkeys(common_names))
mapping = list(zip(icd_codes, common_names))
print("{} {}".format(type(mapping[0][0]), type(mapping[0][1])))
#for icd_code, common_name in mapping:
#print("{} {}".format(icd_code, common_name))
#create offline sqlite3 database
conn = sqlite3.connect('medi_colab.db')
#create a cursor
c = conn.cursor()
#create icd_codes table
c.execute("""CREATE TABLE icd_codes (icd_code VARCHAR(10) PRIMARY KEY,
common_name VARCHAR(50) NOT NULL)""")
#commit changes to the database
conn.commit()
#insert mapped list rows one by one
for icd_code, common_name in mapping:
c.execute("INSERT INTO icd_codes (icd_code, common_name) VALUES
(?, ?)", (icd_code, common_name))
conn.commit()
#extract contents for the icd_sub_codes table
df = df[['icd_sub_code', 'scientific_name', 'icd_code']]
#create icd_sub_codes table
c.execute("""CREATE TABLE icd_sub_codes
(icd_sub_code VARCHAR(10) PRIMARY KEY,
scientific_name TEXT,
icd_code VARCHAR(50),
FOREIGN KEY(icd_code) REFERENCES icd_codes(icd_code))""")
#append the rows to the table
df.to_sql('icd_sub_codes', con = conn, if_exists = 'append', index =
False)
conn.commit()
print("TABLE icd_sub_codes has been successfully populated")
autocomplete.py:
import sqlite3, os
path = '/.../MedRec/'
class DiseaseList:
def __init__(self):
self.conn = sqlite3.connect(path + 'databases/medi_colab.db')
self.c = self.conn.cursor()
def generate_common_names_list(self):
#accept common names output column from DB
self.c.execute("""SELECT * FROM icd_codes""")
names = self.c.fetchall() #get output tuples
common_names = [''] #initialize a list with an empty string
#extract common names from output tuples into a list
for common_name in names:
name = common_name[0] + ' - ' + common_name[1]
common_names.append(name)
return common_names
def generate_scientific_names_list(self, icd_code):
#get icd_sub_code and sub disease name from common name
self.c.execute("""SELECT * FROM icd_sub_codes WHERE icd_code =
'{}'""".format(icd_code))
return self.c.fetchall()
autocompletecombo.py:
import sys
from PyQt5.QtWidgets import QComboBox, QCompleter, QApplication,
QWidget
from PyQt5.QtCore import QSortFilterProxyModel, Qt
class autocompleteGUI(QComboBox):
def __init__(self, parent = None):
super(autocompleteGUI, self).__init__(parent)
self.setFocusPolicy(Qt.StrongFocus)
self.setEditable(True)
# add a filter model to filter matching items
self.pFilterModel = QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.pFilterModel.setSourceModel(self.model())
# add a completer, which uses the filter model
self.completer = QCompleter(self.pFilterModel, self)
# always show all (filtered) completions
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
self.setCompleter(self.completer)
self.resize(700, 30)
# connect signals
def filter(text):
self.pFilterModel.setFilterFixedString(str(text))
self.lineEdit().textEdited.connect(filter)
self.completer.activated.connect(self.on_completer_activated)
# on selection of an item from the completer, select the
corresponding item from combobox
def on_completer_activated(self, text):
if text:
index = self.findText(str(text))
self.setCurrentIndex(index)
dropdown.py:
from PyQt5.QtWidgets import QComboBox
class dropdownMenu(QComboBox):
def __init__(self, parent = None):
super(dropdownMenu, self).__init__(parent)
self.resize(700, 30)
self.show()
formwindow.py:
import sys
path = '/.../MedRec'
sys.path.append(path + '/data/')
sys.path.append(path + '/GUI/')
from autocomplete import DiseaseList
from autocompletecombo import autocompleteGUI
from dropdown import dropdownMenu
from PyQt5.QtWidgets import QMainWindow
class formwindowGUI(QMainWindow):
def __init__(self, parent = None):
super(formwindowGUI, self).__init__(parent)
self.common_names = []
self.scientific_names = []
self.dl = DiseaseList()
self.initUI()
def initUI(self):
ac = autocompleteGUI(self)
dm = dropdownMenu(self)
#add common names to autocomplete GUI
self.common_names = self.dl.generate_common_names_list()
ac.addItems(self.common_names)
self.setGeometry(150, 150, 1080, 720)
ac.move(20, 50)
dm.move(20, 90)
self.show()
ac.activated.connect(self.initialize_subdisease_list)
#connect to generate_scientific_diseases_list in
#data.autocomplete.DiseaseList
def initialize_subdisease_list(self, index):
#reference disease name by index
common_name = self.common_names[index]
#retrieve ICD Code
icd_code = common_name.split(' ')[0]
#if list is not empty, remove all contents
if not (not self.scientific_names):
del self.scientific_names[:]
temp = self.dl.generate_scientific_names_list(icd_code)
for item in temp:
final = item[0] + ' - ' + item[1] + ' - ' + item[2]
self.scientific_names.append(final)
print(self.scientific_names)
#dm.addItems(self.scientific_names)
我希望在运行时在autocompleteGUI小部件的项目列表中选择一个项目时,使用在initialize_subdisease_list()函数中生成的科学名称列表中的值填充dropdownMenu类实例dm。
我已经尝试了以下方法:
class formwindowGUI(QMainWindow):
def __init__(self, parent = None):
super(formwindowGUI, self).__init__(parent)
self.ac = autocompleteGUI()
self.dm = dropdownMenu()
这将导致两个单独的GUI窗口,其中自动完成组合框与主窗口GUI分开显示,并且根本不起作用。
有人可以建议我解决这个问题吗?
答案 0 :(得分:1)
可以使用QSqlQueryModel来代替使您复杂的逻辑,
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('medi_colab.db')
if not db.open():
QtWidgets.QMessageBox.critical(None, QtWidgets.qApp.tr("Cannot open database"),
QtWidgets.qApp.tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information "
"how to build it.\n\n"
"Click Cancel to exit."),
QtWidgets.QMessageBox.Cancel)
return False
return True
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
combo_icd_codes = QtWidgets.QComboBox()
self.model_ics_codes = QtSql.QSqlQueryModel(self)
combo_icd_codes.setModel(self.model_ics_codes)
self.combo_icd_sub_codes = QtWidgets.QComboBox()
self.model_ics_sub_codes = QtSql.QSqlQueryModel(self)
self.combo_icd_sub_codes.setModel(self.model_ics_sub_codes)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(combo_icd_codes, 0, 0)
lay.addWidget(self.combo_icd_sub_codes, 0, 1)
lay.setRowStretch(1, 1)
combo_icd_codes.currentIndexChanged[int].connect(self.on_currentIndexChanged)
query = QtSql.QSqlQuery('''SELECT icd_code || ' ' || common_name AS string_join, icd_code
FROM icd_codes''')
query.exec_()
self.model_ics_codes.setQuery(query)
combo_icd_codes.setCurrentIndex(0)
@QtCore.pyqtSlot(int)
def on_currentIndexChanged(self, index):
ix = self.model_ics_codes.index(index, 1)
icd_sub_code = self.model_ics_codes.data(ix)
query = QtSql.QSqlQuery('''SELECT icd_sub_code || ' ' || scientific_name || ' ' || icd_code AS string_join
FROM icd_sub_codes
WHERE icd_code = ?''')
query.addBindValue(icd_sub_code)
query.exec_()
self.model_ics_sub_codes.setQuery(query)
self.combo_icd_sub_codes.setCurrentIndex(0)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
w = MainWindow()
w.show()
sys.exit(app.exec_())