I'm looking for help regarding how to add a QTableView inside a QGroupBox (this is because i need to create 4 QTableView each displaying one of each possible Status 'In QC','Ready for QC','In Progress','Pending').
The following code currently generates a program that displays a Single QTableView, that refreshes every 5 seconds with new data, the only one that matters is the Status (currently represented as column F) as the rest of the data is displayed for identification purposes. (Please note that in this example i use a code that generates automatically data to display in the QTableView, as this Table actually feeds from an Excel file, going to attach the code that reads the excel file at the end of this post):
import sys
import pandas as pd
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QAbstractTableModel, QObject, Qt
from PyQt5.QtGui import QBrush
from PyQt5.QtWidgets import QApplication, QTableView
import threading
class PandasManager(QObject):
dataFrameChanged = pyqtSignal(pd.DataFrame)
def start(self):
self.t = threading.Timer(0, self.load)
self.t.start()
def load(self):
import random
headers = list("ABCDEFG")
data = [random.sample(range(255), len(headers)) for _ in headers]
for d in data:
d[5] = random.choice(["Ready for QC", "In Progress", "Pending", "In QC"])
df = pd.DataFrame(data, columns=headers,)
self.dataFrameChanged.emit(df)
self.t = threading.Timer(5.0, self.load)
self.t.start()
def stop(self):
self.t.cancel()
class PandasModel(QAbstractTableModel):
def __init__(self, df=pd.DataFrame()):
QAbstractTableModel.__init__(self)
self._df = df
#pyqtSlot(pd.DataFrame)
def setDataFrame(self, df):
self.beginResetModel()
self._df = df
self.endResetModel()
def rowCount(self, parent=None):
return self._df.shape[0]
def columnCount(self, parent=None):
return self._df.shape[1]
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.BackgroundRole:
if self.columnCount() >= 6:
it = self._df.iloc[index.row(), 5]
if it == "Ready for QC":
return QBrush(Qt.yellow)
if it == "In Progress":
return QBrush(Qt.green)
if role == Qt.DisplayRole:
return str(self._df.iloc[index.row(), index.column()])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._df.columns[col]
return None
if __name__ == "__main__":
app = QApplication(sys.argv)
w = QTableView()
model = PandasModel()
w.setModel(model)
w.show()
manager = PandasManager()
manager.dataFrameChanged.connect(model.setDataFrame)
manager.start()
ret = app.exec_()
manager.stop()
sys.exit(ret)
Hopefully this explains my question, as i have been struggling on how to use QGroupBox and how to add the QTableView as I'm using it this way.
Kind Regards,
PS: Attaching code that reads from an excel file
def load(self):
weekNumber = date.today().isocalendar()[1]
aux = pd.read_excel("PCS tasks 2020.xlsm", sheet_name="W" + str(weekNumber))
today = datetime.today()
df = aux[aux["Date Received"] == today.strftime("%Y-%d-%m")]
df = df[
[
"Requestor",
"Subject",
"Task type",
"Created by",
"QC Executive",
"Status",
]
].fillna("")
df = df[df["Status"] != "Completed"]
self.dataFrameChanged.emit(df)
self.t = threading.Timer(5.0, self.load)
self.t.start()
As the example of the QGroupBox docs shows, you must use a layout that allows you to distribute the widgets (QGridLayout, QHBoxLayout, QVBoxLayout, etc.) and set it in the QGroupBox:
if __name__ == "__main__":
app = QApplication(sys.argv)
w = QTableView()
model = PandasModel()
w.setModel(model)
groupbox = QGroupBox()
lay = QVBoxLayout()
lay.addWidget(w)
groupbox.setLayout(lay)
groupbox.show()
manager = PandasManager()
manager.dataFrameChanged.connect(model.setDataFrame)
manager.start()
ret = app.exec_()
manager.stop()
sys.exit(ret)
Related
I'm relatively new to PyQt5, so it may be a simple mistake, but here is my problem.
So my goal is to have a GUI where you can select filters and input data into these filters. Then click a "search" button and have a new window pop up with your filtered results.
The pop up window works perfectly fine when the dataframe has no filters applied, but as soon as I try to filter the dataframe, my GUI will crash after pressing "search".
Here is my code, the issue is in the "search_clicked" function. If you have any solutions or suggestions it would be extremely helpful.
I found out that it was because df was written before the class. After moving it to the init method and making it self.df, the code works fine
import sys
import csv
import pandas as pd
import numpy as np
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QAbstractTableModel, QSortFilterProxyModel, Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QApplication,
QWidget,
QPushButton,
QRadioButton,
QHBoxLayout,
QVBoxLayout,
QLabel,
QLineEdit,
QListWidget,
QButtonGroup,
QTableView,
QGroupBox,
QDialog
)
def data_parser():
df = pd.read_csv("cleaned_crime_data.csv")
df.drop(["Unnamed: 0"], inplace = True, axis = 1)
return df
df = data_parser()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Crime Search")
#hbox0 & hbox1
self.v_button = QRadioButton("Violent")
self.nv_button = QRadioButton("Not Violent")
self.both_button = QRadioButton("Both")
self.filter_label = QLabel("Filter/s:")
self.date_button = QPushButton("Date")
self.day_button = QPushButton("Week Day")
self.month_button = QPushButton("Month")
self.year_button = QPushButton("Year")
self.time_button = QPushButton("Time of Day")
self.neighborhood_button = QPushButton("Neighborhood")
self.data_label = QLabel("Data:")
self.results = QTableView()
self.search = QPushButton("Search")
self.date_box = QLineEdit("2010-05-25")
self.day_box = QLineEdit("Friday")
self.month_box = QLineEdit("May")
self.year_box = QLineEdit("2010")
self.time_box = QLineEdit("Afternoon")
self.neighborhood_box = QLineEdit("Georgia Tech")
self.model = pandasModel(df)
self.results.setModel(self.model)
proxyModel = QSortFilterProxyModel(self)
proxyModel.setSourceModel(self.model)
self.results.setModel(proxyModel)
groupBox = QGroupBox()
groupBoxLayout = QVBoxLayout()
groupBox.setLayout(groupBoxLayout)
groupBoxLayout.addWidget(self.v_button)
groupBoxLayout.addWidget(self.nv_button)
groupBoxLayout.addWidget(self.both_button)
self.search.setFont(QFont("",25))
self.search.setAutoDefault(True)
self.both_button.setChecked(True)
self.date_box.setEnabled(False)
self.day_box.setEnabled(False)
self.month_box.setEnabled(False)
self.year_box.setEnabled(False)
self.time_box.setEnabled(False)
self.neighborhood_box.setEnabled(False)
self.date_button.pressed.connect(self.date_clicked)
self.day_button.pressed.connect(self.day_clicked)
self.month_button.pressed.connect(self.month_clicked)
self.year_button.pressed.connect(self.year_clicked)
self.time_button.pressed.connect(self.time_clicked)
self.neighborhood_button.pressed.connect(self.neighborhood_clicked)
self.search.pressed.connect(self.search_clicked)
###Layout####
hbox0 = QHBoxLayout()
hbox0.addWidget(self.filter_label)
# hbox0.addWidget(self.v_button)
# hbox0.addWidget(self.nv_button)
# hbox0.addWidget(self.both_button)
#hbox0.addWidget(groupBox)
hbox1 = QHBoxLayout()
hbox1.addWidget(self.date_button)
hbox1.addWidget(self.day_button)
hbox1.addWidget(self.month_button)
hbox1.addWidget(self.year_button)
hbox1.addWidget(self.time_button)
hbox1.addWidget(self.neighborhood_button)
hbox1.addWidget(groupBox)
# hbox1.addWidget(self.v_button)
# hbox1.addWidget(self.nv_button)
# hbox1.addWidget(self.both_button)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.date_box)
hbox2.addWidget(self.day_box)
hbox2.addWidget(self.month_box)
hbox2.addWidget(self.year_box)
hbox2.addWidget(self.time_box)
hbox2.addWidget(self.neighborhood_box)
hbox2.addWidget(self.search)
hbox3 = QHBoxLayout()
hbox3.addWidget(self.data_label)
# hbox3.addWidget(self.search)
vbox1 = QVBoxLayout()
vbox1.addWidget(self.results)
vbox_main = QVBoxLayout()
vbox_main.addLayout(hbox0)
vbox_main.addLayout(hbox1)
vbox_main.addLayout(hbox2)
vbox_main.addLayout(hbox3)
vbox_main.addLayout(vbox1)
self.setLayout(vbox_main)
###Fucntions###
def date_clicked(self):
if self.date_box.isEnabled():
self.date_box.setEnabled(False)
else:
self.date_box.setEnabled(True)
def day_clicked(self):
if self.day_box.isEnabled():
self.day_box.setEnabled(False)
else:
self.day_box.setEnabled(True)
def month_clicked(self):
if self.month_box.isEnabled():
self.month_box.setEnabled(False)
else:
self.month_box.setEnabled(True)
def year_clicked(self):
if self.year_box.isEnabled():
self.year_box.setEnabled(False)
else:
self.year_box.setEnabled(True)
def time_clicked(self):
if self.time_box.isEnabled():
self.time_box.setEnabled(False)
else:
self.time_box.setEnabled(True)
def neighborhood_clicked(self):
if self.neighborhood_box.isEnabled():
self.neighborhood_box.setEnabled(False)
else:
self.neighborhood_box.setEnabled(True)
def search_clicked(self):
##This is the part that won't work##
# if self.date_box.isEnabled():
# df = df.mask((df["Occur Date"] == self.date_box.text)).dropna()
# if self.day_box.isEnabled():
# df = df.mask((df["Day Occured"] == self.day_box.text)).dropna()
# if self.month_box.isEnabled():
# df = df.mask((df["Month Occured"] == self.month_box.text)).dropna()
# if self.year_box.isEnabled():
# df = df.mask((df["Year Occured"] == self.year_box.text)).dropna()
# if self.time_box.isEnabled():
# df = df.mask((df["Time of Day"] == self.month_box.text)).dropna()
# if self.neighborhood_box.isEnabled():
# df = df.mask((df["Neighborhood"] == self.neighborhood_box.text)).dropna()
# if self.v_button.isChecked():
# df = df.mask((df["Violent"] == False )).dropna()
# if self.nv_button.isChecked():
# df = df.mask((df["Violent"] == True )).dropna()
self.launchPopup(df)
def launchPopup(self, dataframe):
pop = Popup(dataframe, self)
pop.show()
### Popup Window ###
class Popup(QDialog):
def __init__(self, dataframe, parent):
super().__init__(parent)
#self.setModal(True)
self.resize(950, 500)
self.view = QTableView()
self.view.setModel(pandasModel(dataframe))
vbox = QVBoxLayout()
vbox.addWidget(self.view)
self.setLayout(vbox)
### Pandas DataFrame ###
class pandasModel(QAbstractTableModel):
def __init__(self, data):
QAbstractTableModel.__init__(self)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parnet=None):
return self._data.shape[1]
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[col]
return None
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
results.resize(800, 600)
results.show()
import sys
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QApplication, QItemDelegate, QWidget, QTableWidget, QTableWidgetItem, QPushButton, QHeaderView, QHBoxLayout, QVBoxLayout
from PyQt6.QtCore import Qt
import pandas as pd
class ComboBoxDelegate(QItemDelegate):
def __init__(self, parent=None):
super(ComboBoxDelegate, self).__init__(parent)
self.items = []
def setItems(self, items):
self.items = items
def createEditor(self, widget, option, index):
editor = QtWidgets.QComboBox(widget)
editor.addItems(self.items)
return editor
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.ItemDataRole.EditRole)
if value:
editor.setCurrentText(str(value))
print("Data Changed")
def setModelData(self, editor, model, index):
model.setData(index, editor.currentIndex(), Qt.ItemDataRole.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 700, 500
self.resize(self.window_width, self.window_height)
self.setWindowTitle('Load Excel (or CSV) data to QTableWidget')
layout = QVBoxLayout()
self.setLayout(layout)
self.table = QTableWidget()
layout.addWidget(self.table)
self.button = QPushButton('&Load Data')
self.button.clicked.connect(lambda _, xl_path=excel_file_path,: self.loadExcelData(xl_path))
layout.addWidget(self.button)
def loadExcelData(self, excel_file_dir):
df = pd.read_csv(excel_file_dir)
if df.size == 0:
return
df.fillna('', inplace=True)
self.table.setRowCount(df.shape[0])
self.table.setColumnCount(df.shape[1])
self.table.setHorizontalHeaderLabels(df.columns)
# returns pandas array object
for row in df.iterrows():
values = row[1]
for col_index, value in enumerate(values):
if isinstance(value, (float, int)):
value = '{0:0,.0f}'.format(value)
tableItem = QTableWidgetItem(str(value))
self.table.setItem(row[0], col_index, tableItem)
self.create_delegate(self.table)
self.table.setColumnWidth(2, 300)
def create_delegate(self, table):
test_del = ComboBoxDelegate()
test_list = ["Gravity Main", "Manhole", "Lateral"]
test_del.setItems(test_list)
table.setItemDelegateForColumn(0, test_del)
if __name__ == '__main__':
excel_file_path = "[Your CSV]"
app = QApplication(sys.argv)
app.setStyleSheet('''
QWidget {
font-size: 17px;
}
''')
myApp = MyApp()
myApp.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing Window...')
Extension to previous question
Change the file directory to a random csv.
This populates the QTableWidget and does the same thing as my main program.
The QTableWidget does not save the changes.
My goal is to be able to populate multiple columns with different options based on the csv that is loaded. I had a working version but using QTableView instead of QTableWidget and I am working on transferring that progress.
The issue is caused by a code generation bug, according to the PyQt maintainer.
It should have been fixed in the following PyQt6 snapshots, so it's very likely that if you do a pip update you'll get the working version already, otherwise wait a couple of days and keep an eye on the changelog of the official site.
I have created a simple window with two buttons and a table view in Qt designer and then save my ui as user_interface.ui. Here is the user_interface.
Then, I use the following code to generate some random data and display them on the window with the Generate data and display button click. I also have a save button to give the user the option to save the generated data as csv:
import sys
import pandas as pd
from numpy.random import randn
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.uic import loadUiType
ui,_=loadUiType('user_interface.ui')
class MainApp(QMainWindow, ui):
def __init__(self, parent=None):
QMainWindow.__init__(self)
self.setupUi(self)
self.generate_table.clicked.connect(self.generate_data)
def generate_data(self):
df = pd.DataFrame(randn(5,4),index='A B C D E'.split(),columns='W X Y Z'.split())
model = pandasModel(df)
self.tableView.setModel(model)
self.save_as_csv.clicked.connect(lambda: self.save_data_as_csv(df))
def save_data_as_csv(self, df):
name = QFileDialog.getSaveFileName(self, 'Save File', filter='*.csv')
if(name[0] == ''):
pass
else:
df.to_csv(name[0], index = False)
class pandasModel(QAbstractTableModel):
def __init__(self, data):
QAbstractTableModel.__init__(self)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parnet=None):
return self._data.shape[1]
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[col]
return None
def main():
app=QApplication(sys.argv)
QApplication.processEvents()
window = MainApp()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
When I hit the Generate data and display button, it works fine and I see the generated table. If I keep hitting this button, I do see the random numbers change and it is what I want.
The problem is that when I want to save the generated data, If I have clicked the Generate data and display 20 times to change the data, I will be asked 20 times (except if I hit Cancel in the save popup window) and it basically is trying to save all the dataframes that have been generated on each click of the Generate data and display button. All I want to save is the most recent generated data right before I hit the Save as csv button. I can't figure out what I need to do to achieve that?
This is occurring because another instance of the signal is connected to save_data_as_csv each time generate_data is called. Instead declare the signal connection one time in the constructor and keep a pointer to the most recent dataframe in your class (self.df) so it no longer requires passing the dataframe as an argument.
class MainApp(QMainWindow, ui):
def __init__(self, parent=None):
QMainWindow.__init__(self)
self.setupUi(self)
self.generate_table.clicked.connect(self.generate_data)
self.save_as_csv.clicked.connect(self.save_data_as_csv)
def generate_data(self):
self.df = pd.DataFrame(randn(5,4),index='A B C D E'.split(),columns='W X Y Z'.split())
model = pandasModel(self.df)
self.tableView.setModel(model)
def save_data_as_csv(self):
name = QFileDialog.getSaveFileName(self, 'Save File', filter='*.csv')
if(name[0] == ''):
pass
else:
self.df.to_csv(name[0], index = False)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Widget(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
hlay = QHBoxLayout(self)
self.listview = QListView()
self.listview2 = QListView()
hlay.addWidget(self.listview)
hlay.addWidget(self.listview2)
path = r'C:\Users\Desktop\Project'
self.fileModel = QFileSystemModel()
self.fileModel.setFilter(QDir.NoDotAndDotDot | QDir.Files)
self.listview.setRootIndex(self.fileModel.index(path))
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I want to display the files in my listview from my folder with path described in the code and able to
select them, the files I selected will be displayed in my listview2, However, the listview doesn't show
the files in this path. Can anyone help me with it?
The files are not displayed because you have not set a rootPath in the QFileSystemModel.
On the other hand the second QListView must have a model where items are added or removed as they are selected or deselected, for this you must use the selectionChanged signal of selectionModel() of the first QListView, that signal transports the information of the selected and deselected items.
To change the color you must obtain the QStandardItem and use the setData() method with the Qt::BackgroundRole role. In the example in each second the color is changed randomly
import sys
import random
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(Widget, self).__init__(*args, **kwargs)
self.listview = QtWidgets.QListView()
self.listview2 = QtWidgets.QListView()
path = r'C:\Users\Desktop\Project'
self.fileModel = QtWidgets.QFileSystemModel(self)
self.fileModel.setRootPath(path)
self.fileModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Files)
self.listview.setModel(self.fileModel)
self.listview.setRootIndex(self.fileModel.index(path))
self.listview.selectionModel().selectionChanged.connect(self.on_selectionChanged)
self.listview.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.model = QtGui.QStandardItemModel(self)
self.listview2.setModel(self.model)
hlay = QtWidgets.QHBoxLayout(self)
hlay.addWidget(self.listview)
hlay.addWidget(self.listview2)
timer = QtCore.QTimer(self, interval=1000, timeout=self.test_color)
timer.start()
def on_selectionChanged(self, selected, deselected):
roles = (QtCore.Qt.DisplayRole,
QtWidgets.QFileSystemModel.FilePathRole,
QtWidgets.QFileSystemModel.FileNameRole,
QtCore.Qt.DecorationRole)
for ix in selected.indexes():
it = QtGui.QStandardItem(ix.data())
for role in roles:
it.setData(ix.data(role), role)
it.setData(QtGui.QColor("green"), QtCore.Qt.BackgroundRole)
self.model.appendRow(it)
filter_role = QtWidgets.QFileSystemModel.FilePathRole
for ix in deselected.indexes():
for index in self.model.match(ix.parent(), filter_role, ix.data(filter_role), -1, QtCore.Qt.MatchExactly):
self.model.removeRow(index.row())
def test_color(self):
if self.model.rowCount() > 0:
n_e = random.randint(0, self.model.rowCount())
rows_red = random.sample(range(self.model.rowCount()), n_e)
for row in range(self.model.rowCount()):
it = self.model.item(row)
if row in rows_red:
it.setData(QtGui.QColor("red"), QtCore.Qt.BackgroundRole)
else:
it.setData(QtGui.QColor("green"), QtCore.Qt.BackgroundRole)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I've implemented a very simple log viewer in Python using PyQt4.
I am interested in using it to follow the execution of a program, so the list view has to be refreshed when a new line is appended to the log file.
Here is my implementation (without the watch):
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class LogEntryModel(QAbstractListModel):
def __init__(self, logfile, parent=None):
super(LogEntryModel, self).__init__(parent)
self.slurp(logfile)
def rowCount(self, parent=QModelIndex()):
return len(self.entries)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.entries[index.row()])
else:
return QVariant()
def slurp(self, logfile):
self.entries = []
with open(logfile, 'rb') as fp:
for line in fp.readlines():
tokens = line.strip().split(' : ')
sender = tokens[2]
message = tokens[4]
entry = "%s %s" % (sender, message)
self.entries.append(entry)
class LogViewerForm(QDialog):
def __init__(self, logfile, parent=None):
super(LogViewerForm, self).__init__(parent)
# build the list widget
list_label = QLabel(QString("<strong>MoMo</strong> Log Viewer"))
list_model = LogEntryModel(logfile)
self.list_view = QListView()
self.list_view.setModel(list_model)
list_label.setBuddy(self.list_view)
# define the layout
layout = QVBoxLayout()
layout.addWidget(list_label)
layout.addWidget(self.list_view)
self.setLayout(layout)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = LogViewerForm(sys.argv[1])
form.show()
app.exec_()
As presented, the application works as expected: open the file, parse the contents (split at ' : ' and create a list), and display the list using a QListView.
There is a QFileSystemWatcher class which emits a fileChanged signal, but I don't know where to connect it and how to trigger an add a row to the data and refresh the view event.
Any help?
Thanks.
I am quite new to python and pyqt, but this "works" here:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class LogEntryModel(QAbstractListModel):
def __init__(self, logfile, parent=None):
super(LogEntryModel, self).__init__(parent)
self.slurp(logfile)
self.logfile = logfile
def rowCount(self, parent=QModelIndex()):
return len(self.entries)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.entries[index.row()])
else:
return QVariant()
def slurp(self, logfile):
self.entries = []
with open(logfile, 'rb') as fp:
for line in fp.readlines():
tokens = line.strip().split(' : ')
sender = tokens[2]
message = tokens[4]
entry = "%s %s" % (sender, message)
self.entries.append(entry)
class LogViewerForm(QDialog):
def __init__(self, logfile, parent=None):
super(LogViewerForm, self).__init__(parent)
self.watcher = QFileSystemWatcher([logfile], parent=None)
self.connect(self.watcher, SIGNAL('fileChanged(const QString&)'), self.update_log)
# build the list widget
list_label = QLabel(QString("<strong>MoMo</strong> Log Viewer"))
list_model = LogEntryModel(logfile)
self.list_model = list_model
self.list_view = QListView()
self.list_view.setModel(self.list_model)
list_label.setBuddy(self.list_view)
# define the layout
layout = QVBoxLayout()
layout.addWidget(list_label)
layout.addWidget(self.list_view)
self.setLayout(layout)
def update_log(self):
print 'file changed'
self.list_model.slurp(self.list_model.logfile)
self.list_view.updateGeometries()
if __name__ == "__main__":
app = QApplication(sys.argv)
form = LogViewerForm(sys.argv[1])
form.show()
app.exec_()
But be aware that this is probably not a good way to do it.
You might want to stream the logfile...
Maybe somebody more experienced can help out.