i am new to python, I put a button to refresh the listview and get the information from a .txt file, but it doesn't works :(
Here is the code:
import gtk
actresses = [i.strip().replace("'", "").split() for i in open("lista.txt").readlines()]
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_size_request(350, 250)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
self.set_title("ListView")
self.Boton = gtk.Button("click")
self.Boton.connect("clicked",self.create_list)
self.Boton.show()
vbox = gtk.VBox(False, 8)
sw = gtk.ScrolledWindow()
sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
vbox.pack_start(sw, True, True, 0)
vbox.pack_start(self.Boton, True, True, 0)
store = self.create_model()
treeView = gtk.TreeView(store)
treeView.connect("row-activated", self.on_activated)
treeView.set_rules_hint(True)
sw.add(treeView)
self.create_columns(treeView)
self.statusbar = gtk.Statusbar()
vbox.pack_start(self.statusbar, False, False, 0)
self.add(vbox)
self.show_all()
def create_model(self):
store = gtk.ListStore(str, str, str)
for act in actresses:
store.append([act[0], act[1], act[2]])
return store
def create_columns(self, treeView):
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn("Nombre", rendererText, text=0)
column.set_sort_column_id(0)
treeView.append_column(column)
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn("apellido", rendererText, text=1)
column.set_sort_column_id(1)
treeView.append_column(column)
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn("TamaƱo", rendererText, text=2)
column.set_sort_column_id(2)
treeView.append_column(column)
def on_activated(self, widget, row, col):
model = widget.get_model()
text = model[row][0] + ", " + model[row][1] + ", " + model[row][2]
self.statusbar.push(0, text)
if model[row][0] == "lol":
print "Funciona"
def create_list(self, widget):
# create a TreeView object which will work with our model (ListStore)
self.listview = self.create_model()
self.treeView = gtk.TreeView(self.listview)
self.treeView.set_rules_hint(True)
PyApp()
gtk.main()
Your code has several problems.
First, the create_model method, called by create_list, is not re-reading the file, it is using the object initialized at top-level. To fix this, have create_model invoke the reading code.
More importantly, the create_list method is creating a new tree view, but isn't doing anything with it (other than storing it to a property of the Python instance). As far as the GTK window is concerned, your old tree view is still in the window. There are several ways to fix this:
As a quick fix, you can remove the existing tree view from the VBox, add the new one, and show it. A simpler version is to move the code that creates the vbox to a separate method, remove the vbox with self.remove(self.get_child()) and re-add it. Either of these will accomplish what the code set out to do.
A better fix would be to only recreate the store and switch the tree view to the new store using the set_model method.
Another possibility is to empty the existing store and re-populate it. The tree view will react to the change to the store, and it is not necessary to call set_model, nor any other hint to the tree view.
Related
I'm new on Python GTK and I was developing a simple TreeView that show several data:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# list of tuples for each variable, containing the environment variable name, its path, and the security category
variable_list = [
("$ENV1", "/usr/share/background/image.png", "Image"),
("$ENV2", "/home/user/script.py", "Program"),
("$ENV3", "/usr/share/icons/icon.png", "Image")
]
class TreeViewFilterWindow(Gtk.Window):
def __init__(self):
super().__init__(title="Environment Variable View")
self.set_border_width(10)
# Setting up the self.grid in which the elements are to be positioned
self.grid = Gtk.Grid()
self.grid.set_column_homogeneous(True)
self.grid.set_row_homogeneous(True)
self.add(self.grid)
# Creating the ListStore model
self.variable_liststore = Gtk.ListStore(str, str, str)
for variable_ref in variable_list:
self.variable_liststore.append(list(variable_ref))
self.current_filter_category = None
# Creating the filter, feeding it with the liststore model
self.category_filter = self.variable_liststore.filter_new()
# setting the filter function, note that we're not using the
self.category_filter.set_visible_func(self.category_filter_func)
# creating the treeview, making it use the filter as a model, and adding the columns
self.treeview = Gtk.TreeView(model=self.category_filter)
for i, column_title in enumerate(
["Variable", "Path", "Category"]
):
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
self.treeview.append_column(column)
# creating buttons to filter by Category, and setting up their events
self.buttons = list()
for var_category in ["Image", "Program"]:
button = Gtk.Button(label=var_category)
self.buttons.append(button)
button.connect("clicked", self.on_selection_button_clicked)
# setting up the layout, putting the treeview in a scrollwindow, and the buttons in a row
self.scrollable_treelist = Gtk.ScrolledWindow()
self.scrollable_treelist.set_vexpand(True)
self.grid.attach(self.scrollable_treelist, 0, 0, 5, 10)
self.grid.attach_next_to(
self.buttons[0], self.scrollable_treelist, Gtk.PositionType.BOTTOM, 1, 1
)
for i, button in enumerate(self.buttons[1:]):
self.grid.attach_next_to(
button, self.buttons[i], Gtk.PositionType.RIGHT, 1, 1
)
self.scrollable_treelist.add(self.treeview)
self.show_all()
def category_filter_func(self, model, iter, data):
"""Tests if the Category in the row is the one in the filter"""
if (
self.current_filter_category is None
or self.current_filter_category == "None"
):
return True
else:
return model[iter][2] == self.current_filter_category
def on_selection_button_clicked(self, widget):
"""Called on any of the button clicks"""
# we set the current category filter to the button's label
self.current_filter_category = widget.get_label()
print("%s category selected!" % self.current_filter_category)
# we update the filter, which updates in turn the view
self.category_filter.refilter()
win = TreeViewFilterWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
When I run the script, the content of each row cannot be selected. Is there a way to select the content of these rows in order that I can right-click and copy the content?
In case I would like to highlight with the mouse cursor the text and then directly copy the highlighted content on the clipboard with a small message saying "The content has been copied", how could I reach these purposes?
If selection was possible, this would have to be done by setting a property in Gtk.CellRendererText, but I don't see a property that would make that possible, besides editable:
renderer.set_property("editable", True)
Making the cells editable would certainly allow users to copy from them, but this would suggest the contents could be changed. (If you don't connect to the edited signal, the text reverts after the input. This might feel very counterintuitive.)
If you the time, you could maybe write your own CellRenderer (I have no experience with this)
Another possibility would be to connect to the button-released-event of the Gtk.TreeView and copy the text to the clipboard if the user right-clicks.
Use Gtk.TreeView.get_path_at_pos to get the cell under the cursor.
def listclick(self, listview, event: Gdk.EventButton, *_unused) -> bool:
"""Handler for clicks on the list."""
if (event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 3):
tup = listview.get_path_at_pos(event.x, event.y)
if tup is not None:
path, col, *unused = tup
# Copy to Clipboard, depending on Path and Column
# ...
return True
return False
This is the code
Entrypoint.py
def Data_For_MakePdf_Db(self):
mese = self.MakePdf_Strip_Month_select.currentText()
anno = self.MakePdf_Strip_Year_select.currentText()
MakeStrip(anno, mese)
return ### Breakpoint here
and MakeStrip.py
class SpecialStyledItemDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super().__init__(parent)
self._values = dict()
def add_text(self, text, row):
self._values[row] = text
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
row = index.row()
if row in self._values:
option.text = self._values[row]
option.displayAlignment = QtCore.Qt.AlignCenter
class MakeStrip(QtWidgets.QWidget):
def __init__(self, anno, mese):
super().__init__()
self.initUI(anno, mese)
def initUI(self, anno, mese):
self.title = "MAMbo - Strips di '%s' '%s' "%(mese, anno)
self.setWindowTitle(self.title)
self.setGeometry(50, 100, 900, 800)
self.callTable(anno, mese)
self.button = QtWidgets.QPushButton(self.tableWidget)
self.button.setGeometry(QtCore.QRect(440, 169, 70, 20))
self.button.setObjectName("button")
self.button.setText("close")
self.layout = QtWidgets.QHBoxLayout(self)
self.layout.addWidget(self.tableWidget)
self.show()
self.button.clicked.connect(self.on_click)
pippo = 0 ### Breakpoint here
def on_click(self):
print('Clicked')
# Functions.message_handler(message = "THIS WILL CLOSE THE APP")
return
def callTable(self, anno, mese):
# Create table
self.tableWidget = QtWidgets.QTableWidget()
self.tableWidget.move(100, 700)
self.tableWidget.setRowCount(33)
self.tableWidget.setColumnCount(3)
self.special_delegate = SpecialStyledItemDelegate()
self.tableWidget.setItemDelegate(self.special_delegate)
h_header = self.tableWidget.horizontalHeader()
h_header.hide()
for i in range(h_header.count()):
h_header.setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)
v_header = self.tableWidget.verticalHeader()
v_header.hide()
v_header.setDefaultSectionSize(13)
self.tableWidget.setSpan(1, 0, 1, 3)
self.tableWidget.setSpan(0, 0, 1, 3)
...
pluto = 0
def on_click(self):
print('Clicked')
return
I use pycharm
Main problem
If I run the script I see for a fraction of second the result of Makescript even if there a push button
Alternative problem
If I debug it I need to put some breakpoints as shown in the scripts to see the result of the script
I know that the debugger keeps alive the connection but why do I need to put breakpoints in those positions to see the result?
The problem is in the following line:
MakeStrip(anno, mese)
What happens there is that you create an instance of MakeStrip which has absolutely no reference. The result is that it's created and immediately garbage collected as soon as its __init__ returns.
Imagine doing something like this:
def Data_For_MakePdf_Db(self):
list()
As soon as no reference to an object is left, python automatically destroys it. In the case above, you create an instance without any reference, so it gets immediately deleted.
Note that creating a local reference (a variable that exists only in the function) might be a solution, but since there is no locking, you'll have almost the same results, because the function will immediately returns, causing the instance to be destroyed as well:
def Data_For_MakePdf_Db(self):
strip = MakeStrip(anno, mese)
A possibility is to create a persistent reference, by making the object a member of the current instance:
def Data_For_MakePdf_Db(self):
self.strip = MakeStrip(anno, mese)
This has some, possibly unwanted, side effects: first of all, you could still switch between the current window to the new one (which will probably make things a bit confusing), and, most importantly, if you call Data_For_MakePdf_Db again while another MakeStrip window already exists, it will be probably destroyed and replaced by a new one.
A better and more consistent solution is to have MakeStrip a subclass of QDialog instead, and use its exec_(): it will make it a modal window and will return control only when the window is finally closed.
def Data_For_MakePdf_Db(self):
MakeStrip(self, anno, mese).exec_()
class MakeStrip(QtWidgets.QDialog):
def __init__(self, parent, anno, mese):
super().__init__(parent)
self.initUI(anno, mese)
def initUI(self, anno, mese):
# ...
self.button.clicked.connect(self.accept)
Note that in this specific case we can even create the dialog without the local or instance reference, thanks to the fact that exec_ creates an event loop that blocks the execution until the dialog is closed.
This is always a good idea, though, as you might need to know if the dialog was actually "accepted" or "rejected", or need access to some of the dialog's objects.
In that case, a local reference is required:
def Data_For_MakePdf_Db(self):
dialog = MakeStrip(<b>self</b>, anno, mese)
if dialog.exec_():
print(dialog.tableWidget.rowCount())
PS: capitalized names should always be used only for classes and constants, not for functions, so it should be data_for_MakePdf_Db; while you can name your function as you like, this standard convention is highly suggested, as it improves readability (it makes clear distinction between classes and functions). Read more on the official Style Guide for Python Code.
I have a program written in Python 3 and using Drag and Drop. I want to make Video tutorials. But when the Video capture is working, Drop fails. The capture program seems to intercept some signal.
I have tried several programs (Jing and others) with the same result. I am testing with a very simple Python script. When the capture is working, the lines which normally indicate the drop location do not appear. The get_data and the received_data functions are not launched.
I am in Windows 8. I have not tested in Linux.
Below, my python3 test code.
#!/usr/bin/env python
# example treeviewdnd.py modified
from gi.repository import Gtk, Gdk, Pango, GObject
class TreeViewDnDExample:
TARGETS = [
('MY_TREE_MODEL_ROW', Gtk.TargetFlags.SAME_WIDGET, 0),
('text/plain', 0, 1),
('TEXT', 0, 2),
('STRING', 0, 3),
]
# close the window and quit
def delete_event(self, widget, event, data=None):
Gtk.main_quit()
return False
def clear_selected(self, button):
selection = self.treeview.get_selection()
model, iter = selection.get_selected()
if iter:
model.remove(iter)
return
def __init__(self):
# Create a new window
self.window = Gtk.Window()
self.window.set_title("URL Cache")
self.window.set_size_request(200, 200)
self.window.connect("delete_event", self.delete_event)
self.scrolledwindow = Gtk.ScrolledWindow()
self.vbox = Gtk.VBox()
self.hbox = Gtk.HButtonBox()
self.vbox.pack_start(self.scrolledwindow, True, True, 0)
self.vbox.pack_start(self.hbox, False, True, 0)
self.b0 = Gtk.Button('Clear All')
self.b1 = Gtk.Button('Clear Selected')
self.hbox.pack_start(self.b0, True, True, 0)
self.hbox.pack_start(self.b1, True, True, 0)
# create a liststore with one string column to use as the model
self.liststore = Gtk.ListStore(str)
for a in "abcd" :
self.liststore.append([a])
# create the TreeView using liststore
self.treeview = Gtk.TreeView(self.liststore)
# create a CellRenderer to render the data
self.cell = Gtk.CellRendererText()
# create the TreeViewColumns to display the data
self.tvcolumn = Gtk.TreeViewColumn('URL', self.cell, text=0)
# add columns to treeview
self.treeview.append_column(self.tvcolumn)
self.b0.connect_object('clicked', Gtk.ListStore.clear, self.liststore)
self.b1.connect('clicked', self.clear_selected)
# make treeview searchable
self.treeview.set_search_column(0)
# Allow sorting on the column
self.tvcolumn.set_sort_column_id(0)
# Allow enable drag and drop of rows including row move
self.treeview.enable_model_drag_source( Gdk.ModifierType.BUTTON1_MASK,
self.TARGETS,
Gdk.DragAction.DEFAULT|
Gdk.DragAction.MOVE)
self.treeview.enable_model_drag_dest(self.TARGETS,
Gdk.DragAction.DEFAULT)
self.treeview.drag_dest_add_text_targets()
self.treeview.drag_source_add_text_targets()
self.treeview.connect("drag_data_get", self.drag_data_get_data)
self.treeview.connect("drag_data_received",
self.drag_data_received_data)
self.scrolledwindow.add(self.treeview)
self.window.add(self.vbox)
self.window.show_all()
def drag_data_get_data(self, treeview, context, selection, target_id,
etime):
print("drag get data")
treeselection = treeview.get_selection()
model, iter = treeselection.get_selected()
data = bytes(model.get_value(iter, 0), "utf-8")
selection.set(selection.get_target(), 8, data)
def drag_data_received_data(self, treeview, context, x, y, selection,
info, etime):
print("received")
def main():
Gtk.main()
if __name__ == "__main__":
treeviewdndex = TreeViewDnDExample()
main()
Since I didn't find an answer to the problem in Windows, the solution was to launch the program on a Linux machine where video capture programs does not present the same effect. It was even possible to be connected to the Linux machine with VNCViewer, and make the capture in the Windows box. For demonstration purposes, it is sufficient.
But I am still wondering what prevents Gtk-Windows to receive the drop event.
I m able to dynamically add a layout to QHBoxLayout in pyqt , however I m unable to remove them once added.
Main aim is to dynamically add and remove a layout based on the Radio Button selected.
def SearchTab(self):
self.layout = QVBoxLayout()
button_layout = QHBoxLayout()
radio_button_1 = QRadioButton("Search")
radio_button_2 = QRadioButton("Update")
button_layout.addWidget(radio_button_1)
button_layout.addWidget(radio_button_2)
self.layout.addItem(button_layout)
radio_button_1.toggled.connect(lambda :self.SelectButtonCheck(radio_button_1))
radio_button_1.toggled.connect(lambda :self.UpdateButtonCheck(radio_button_2))
self.setTabText(0,"Search")
self.tab1.setLayout(self.layout)
def SelectButtonCheck(self,b):
if b.text() == "Search":
if b.isChecked():
print(b.text()+ "is selected")
self.pg_details = pgd.PGDetails()
layout = self.pg_details.returnLayout()
self.layout.addLayout(layout)
def UpdateButtonCheck(self,b):
if b.text() == "Update":
if b.isChecked():
print(b.text()+ " is selected")
for i in range(self.layout.count()):
print(self.layout.itemAt(i))
temp_layout = self.layout.itemAt(i)
widget = temp_layout.widget()
temp_layout.removeItem(temp_layout)
if widget is not None:
widget.deleteLater()
Initial Screen-
Currently I m able to add the layout when "Search" Radio Button is selected --
But Nothing happens when I select "Update" RadioButton
Also find the layouts that have been added-
for i in range(self.layout.count()):
print(self.layout.itemAt(i))
<PyQt5.QtWidgets.QHBoxLayout object at 0x1180ec438>
<PyQt5.QtWidgets.QFormLayout object at 0x1180ff828>
Layouts are being added but not getting removed.
Any leads would be helpful , in what I m missing here
I was able to solve this. Took me a while but understood what is the arrangement of widgets within the layouts.
I assumed removing the layout will cascade delete the widgets itself.
I used the below function to remove the layout and its widgets corresponding to it.
def SearchTab(self):
self.layout = QVBoxLayout()
button_layout = QHBoxLayout()
radio_button_1 = QRadioButton("Search")
radio_button_2 = QRadioButton("Update")
button_layout.addWidget(radio_button_1)
button_layout.addWidget(radio_button_2)
self.layout.addItem(button_layout)
#createDB()
radio_button_1.toggled.connect(lambda :self.SelectButtonCheck(radio_button_1,self.layout))
radio_button_1.toggled.connect(lambda :self.UpdateButtonCheck(radio_button_2,self.layout))
#layout.addRow("Address",QLineEdit())
self.setTabText(0,"Search")
update_layout = QHBoxLayout()
#update_layout.set
#update_btn = QDialogButtonBox(QDialogButtonBox)
#update_btn.setAlignment(Qt.AlignBottom)
update_layout.setAlignment(QtCore.Qt.AlignTop)
update_btn = QPushButton('Update')
reset_btn = QPushButton('Reset')
#self.layout.addRow(update_layout)
update_layout.addWidget(update_btn)
update_layout.addWidget(reset_btn)
update_btn.clicked.connect(self.createDB)
self.tab1.setLayout(self.layout)
def SelectButtonCheck(self,b,stacklayout):
if b.text() == "Search":
if b.isChecked():
print(b.text()+ "is selected")
self.pg_details = pgd.PGDetails()
layout = self.pg_details.returnLayout()
self.layout.addLayout(layout)
def removeLayout(self,layout):
for i in range(layout.count()):
temp_layout = layout.itemAt(i)
if temp_layout is not None:
widget = temp_layout.widget()
if widget is not None:
widget.deleteLater()
else:
return
if temp_layout.layout() is not None:
self.removeLayout(temp_layout.layout())
def removeFormLayout(self,layout):
if layout is not None:
for i in range(layout.count()):
temp_layout = layout.itemAt(i)
if isinstance(temp_layout.layout(),type(QFormLayout())):
self.removeLayout(temp_layout.layout())
else:
next
else:
return
def UpdateButtonCheck(self,b,stacklayout):
if b.text() == "Update":
if b.isChecked():
print(b.text()+ " is selected")
self.removeFormLayout(stacklayout)
The removeFormLayout function picks out the formlayout that I added with the Search radio button and removeLayout removes all the widgets under it as well.
Open to suggestions and improvements in the method used, I tried it with a couple of layout removals other then FormLayout as well. Currently it is working fine.
Also is anybody aware of how to align the HBoxLayout at the top , the radio button starts from the middle again , I want to align them at the top of the screen
Another way is to do the following. QWidget and thus QGroupBox have a show/hide option.
Note, its best to always hide first, otherwise things get wonky
I have a test function that has the following control logic
if isOn:
self.gb1.hide()
self.gb2.show()
else:
self.gb2.hide()
self.gb1.show()
I created a layout that contains both group boxes above. see the sample logic below. I am sure there is a way to do this without storing the variables in the window class.
def create_layout(self):
ly = QHBoxLayout()
self.gb1 = self.create_gb_test1()
self.gb2 = self.create_gb_test2()
ly.addWidget(self.gb1)
ly.addWidget(self.gb2)
return ly
def create_gb_test1(self):
my_name = inspect.currentframe().f_code.co_name
gb = QGroupBox("Find")
btn_find = QPushButton()
ly_horiz = QHBoxLayout()
ly_horiz.addWidget(QLabel("Find:"))
ly_horiz.addWidget(QLineEdit("Some Text", ))
ly_horiz.addWidget(btn_find)
self.ly_find_only = ly_horiz
gb.setLayout(ly_horiz)
return gb
def btn_open_click(self):
pass
def create_gb_test2(self):
my_name = inspect.currentframe().f_code.co_name
gb = QGroupBox("View")
btn_open = QPushButton
cbo = QComboBox()
cbo.addItems(['a', 'b'])
ly_horiz = QHBoxLayout()
ly_horiz.addWidget(QLabel("Find:"))
ly_horiz.addWidget(cbo)
ly_horiz.addWidget(btn_open)
self.ly_find_only = ly_horiz
gb.setLayout(ly_horiz)
return gb
I did a class that inserts a new tab whenever it is called with a notebook as argument. What I like to do is to associate an appropriate containt to this new tab. I thought that calling my class CreateTab with this widget as argument would be a good idea. But when I make:
>>> notebook.insert_page(treeview, hbox, 0)
I keep having this error:
Gtk-WARNING **: Can't set a parent on widget which has a parent
Clearly, what I would like to do is : whenever I click on a button from my main window, for example 'Fish button', it creates a new tab with my widget displaying 'all the fish from the sea'.
Here is my 'CreateTab' class:
class CreateTab():
def __init__(self, notebook, title):
self.notebook = notebook
self.pages = self.notebook.get_n_pages()
self.create_tab(title + str(self.pages))
self.notebook.set_current_page(self.pages)
def create_tab(self, title):
hbox = Gtk.HBox(False, 0)
label = Gtk.Label(title)
hbox.pack_start(label, True, True, 0)
pixbuf = Gtk.IconTheme.get_default().load_icon(Gtk.STOCK_CLOSE, 16,0)
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
btn = Gtk.Button()
btn.set_focus_on_click(False)
btn.add(image)
hbox.pack_start(btn, False, False, 0)
hbox.show_all()
#widget = Gtk.Label(title)
widget = Gtk.TreeView()
widget.show_all()
self.notebook.insert_page(widget, hbox,self.pages)
btn.connect('clicked', self.on_closetab_button_clicked, widget)
def on_closetab_button_clicked(self, sender, widget):
pagenum = self.notebook.page_num(widget)
self.notebook.remove_page(pagenum)
And for instance, the widget I'd like to associate :
class CellRendererTextWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="CellRendererText Example")
self.set_default_size(200, 200)
self.liststore = Gtk.ListStore(str, str)
self.liststore.append(["Fedora", "http://fedoraproject.org/"])
self.liststore.append(["Slackware", "http://www.slackware.com/"])
self.liststore.append(["Sidux", "http://sidux.com/"])
treeview = Gtk.TreeView(model=self.liststore)
renderer_text = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
treeview.append_column(column_text)
renderer_editabletext = Gtk.CellRendererText()
renderer_editabletext.set_property("editable", True)
column_editabletext = Gtk.TreeViewColumn("Editable Text",
renderer_editabletext, text=1)
treeview.append_column(column_editabletext)
renderer_editabletext.connect("edited", self.text_edited)
self.add(treeview)
def text_edited(self, widget, path, text):
self.liststore[path][1] = text
I would be gratefull for any help or suggestion since I'm stuck in this for two days !
The solution I found is to call my class CreateTab with a tab name (str) and a class in argument in charge to create the content.
For example, from main.py, I launch the creation of a new tab called "Supplier's list":
CreateTab(title='Suppliers's list', Content=Suppliers)
From the class CreateTab, I create a VBox()
container = VBox()
and I launch Content with the new created VBox in argument.
Content(container)
So in Content (which can be whatever I want as Suppliers, Customers, Invoices...), I create all my widgets and I attach them in a grid. Here is a simplified Suppliers class:
class Suppliers(Gtk.Window):
def __init__(self, container):
liststore = Gtk.ListStore(int, str, str, str, str, int)
self.data = session.load_contacts({'type_contact': 'collab'})
for c in self.data:
row = ([c.id, c.nom, c.prenom, c.telephone, c.mail, c.actif])
liststore.append(row)
# creation of a treeview
treeview = Gtk.TreeView(model=liststore)
...
# creation of a ScrolledWindow to attach the treeview
scroll = Gtk.ScrolledWindow()
scroll.add(treeview)
# creation of a check button to filter the treeview
actif_btn = Gtk.CheckButton(label="Active suppliers")
actif_btn.connect('clicked', self.active_selected, liststore)
actif_btn.set_active(True)
# I create a grid to attach every thing
grid = Gtk.Grid()
grid.add(actif_btn)
# I attach every thing to the initial container
container.pack_start(grid, False, False, 10)
container.pack_start(scroll, True, True, 0)
container.show_all()
I hope this will help someone.
I wonder if I can do the same with a window imported from a glade file.