In below picture you can see the 3 parent child window. actually I made one code which will show all child according to parent. that is showing correctly but i want username & password column editable for database parent only(like as 3rd window). other should not be editable.
In my case all child of parent is editable.
here is my code
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gobject
import os
import cairo, gio, pango, pangocairo, atk
class BasicTreeViewExample:
# close the window and quit
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def col1_toggled_cb( self, cell, path, model ):
model[path][1] = not model[path][1]
def on_cell_edited(self, cell, path_string, new_text, model):
print "hi"
#cell.set_property('editable', False)
iter = model.get_iter_from_string(new_text)
path = model.get_path(iter)[0]
column = cell.get_data("username")
def __init__(self):
# Create a new window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Basic TreeView Example")
self.window.set_size_request(400, 400)
self.window.connect("delete_event", self.delete_event)
self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN,gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING)
for parent in range(2):
piter = self.treestore.append(None, ['Computer %i' % parent, False,False, '', ''])
pit = self.treestore.append(piter, ['Drive', False,False, '', ''])
pith = self.treestore.append(piter, ['Database', False,False, '', ''])
for child in range(2):
self.treestore.append(pit, ['child', True,True, '', ''])
for child in range(2):
self.treestore.append(pith, ['child', True,True, 'user', 'psw'])
self.treeview = gtk.TreeView(self.treestore)
self.cell = gtk.CellRendererText()
self.tvcolumn = gtk.TreeViewColumn("Computer Name", self.cell, text=0)
self.cell.set_property( 'editable', False )
self.cell0 = gtk.CellRendererToggle()
self.tvcolumn0 = gtk.TreeViewColumn("Select Drive", self.cell0 , active=1, visible=2)
self.cell0.set_property('activatable', True)
self.cell0.connect( 'toggled', self.col1_toggled_cb, self.treestore )
self.cell1 = gtk.CellRendererText()
self.tvcolumn1 = gtk.TreeViewColumn("username", self.cell1, text=3, visible=2)
self.cell1.set_property( 'editable', True )
self.cell1.connect("editing-started", self.on_cell_edited, self.treestore)
self.cell2 = gtk.CellRendererText()
self.tvcolumn2 = gtk.TreeViewColumn("password", self.cell2, text=4, visible=2)
self.cell2.set_property( 'editable', True )
self.treeview.append_column(self.tvcolumn)
self.treeview.append_column(self.tvcolumn0)
self.treeview.append_column(self.tvcolumn1)
self.treeview.append_column(self.tvcolumn2)
self.treeview.set_reorderable(True)
self.window.add(self.treeview)
self.window.show_all()
def main():
gtk.main()
if __name__ == "__main__":
tvexample = BasicTreeViewExample()
main()
Anybody help me for this problem.
Thanks...
The answer here is similar to the answer to your previous question: you need to extend your tree store with an additional column that specifies the attribute you care about — in this case, editability of username/password cells for a particular row, and connect that store column with the tree view columns that display and edit the username and password.
The provided code simply sets the editable property to true, which means the property is editable everywhere.
There are tutorials that explain the GTK tree view in some detail. Here is a version of the code from the question, modified to match your requirements as I understood them.
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gobject
import os
import cairo, gio, pango, pangocairo, atk
class BasicTreeViewExample:
# close the window and quit
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def col1_toggled_cb( self, cell, path, model ):
model[path][1] = not model[path][1]
def on_cell_edited(self, cell, path_string, new_text, model):
print "hi"
#cell.set_property('editable', False)
iter = model.get_iter_from_string(new_text)
path = model.get_path(iter)[0]
column = cell.get_data("username")
def __init__(self):
# Create a new window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Basic TreeView Example")
self.window.set_size_request(400, 400)
self.window.connect("delete_event", self.delete_event)
self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN,gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
for parent in range(2):
piter = self.treestore.append(None, ['Computer %i' % parent, False,False, '', '', False])
pit = self.treestore.append(piter, ['Drive', False,False, '', '', False])
pith = self.treestore.append(piter, ['Database', False,False, 'user', 'psw', True])
for child in range(2):
self.treestore.append(pit, ['child', True,True, '', '', False])
for child in range(2):
self.treestore.append(pith, ['child', True,True, '', '', False])
self.treeview = gtk.TreeView(self.treestore)
self.cell = gtk.CellRendererText()
self.tvcolumn = gtk.TreeViewColumn("Computer Name", self.cell, text=0)
self.cell.set_property( 'editable', False )
self.cell0 = gtk.CellRendererToggle()
self.tvcolumn0 = gtk.TreeViewColumn("Select Drive", self.cell0 , active=1, visible=2)
self.cell0.set_property('activatable', True)
self.cell0.connect( 'toggled', self.col1_toggled_cb, self.treestore )
self.cell1 = gtk.CellRendererText()
self.tvcolumn1 = gtk.TreeViewColumn("username", self.cell1, text=3, visible=5, editable=5)
self.cell1.connect("editing-started", self.on_cell_edited, self.treestore)
self.cell2 = gtk.CellRendererText()
self.tvcolumn2 = gtk.TreeViewColumn("password", self.cell2, text=4, visible=5, editable=5)
self.treeview.append_column(self.tvcolumn)
self.treeview.append_column(self.tvcolumn0)
self.treeview.append_column(self.tvcolumn1)
self.treeview.append_column(self.tvcolumn2)
self.treeview.set_reorderable(True)
self.window.add(self.treeview)
self.window.show_all()
def main():
gtk.main()
if __name__ == "__main__":
tvexample = BasicTreeViewExample()
main()
Related
So, I'm using GTK+/VLC to create a window with a video playback area and a "next" button.
It starts by playing the first video file and clicking next button will skip to the next media file, playing it. Everything working great so far.
My problem is, if I wait for MediaPlayerEndReached to be fired, button_Next() is executed but the video does not change.
Am I missing anything?
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = []
for fldrs in sorted(listdir(startingPath)):
self.Fldrs.append(join(startingPath,fldrs))
print self.Fldrs
self.num_Fldrs = len(self.Fldrs)
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget):
print 'next!'
num_FldrFiles = len(listdir(self.Fldrs[self.currFldrIdx]))
self.currFileIdx = self.currFileIdx+1 if self.currFileIdx+1<num_FldrFiles else 0
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
print 'now showing' + fileToShow
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.vlcPlayer.play()
def _realized(self, widget, data=None):
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
print "Event reports - finished, playing next"
self.button_Next.clicked()
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()
Your problem is described here:
the libvlc API is not reentrant within its callbacks https://forum.videolan.org/viewtopic.php?f=32&t=80305
and here: https://forum.videolan.org/viewtopic.php?t=82502
You should typically have a mainloop in your application (gobject.mainloop(), or Qt mainloop), so you should instead register a method to restart the player from there
This is bit mucked about with for the file names but your code now registers the GObject.idle_add() function that is required.
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.autoPlay = 0
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = ['/home/public/2005.mp3','/home/public/happy.mp3','/home/public/vp.mp3']
#for fldrs in sorted(listdir(startingPath)):
# self.Fldrs.append(join(startingPath,fldrs))
self.num_Fldrs = len(self.Fldrs) - 1
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget=None):
self.currFileIdx += 1
if self.currFileIdx > self.num_Fldrs:
self.currFileIdx = 0
fileToShow = self.Fldrs[self.currFileIdx]
media = self.vlcInstance.media_new_path(fileToShow)
self.vlcPlayer.set_media(media)
if self.vlcPlayer.play() == -1:
print ("error playing",fileToShow)
else:
print("now playing",fileToShow)
def _realized(self, widget, data=None):
fileToShow = self.Fldrs[self.currFldrIdx]
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
GObject.idle_add(self.on_button_NextImg)
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()
I developed a GUI program based on python Gtk3. In the Main Window there is a button and a progressbar, my purpose is when pressing the button there is another thread running to do some work finally another GTK window shows up to display the result, in the meantime the preogress could update the progress in the main Window correctly.
But I always got a error as below:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted (core dumped)
I really don't know what is going wrong there and have no idea about it, could anyone help taking look at it and provide a example here ?
Thanks a lot !
I developed a test program here as below, I always got the follow errors under Linux platform:
(fileChooser.py:40834): Gtk-CRITICAL **: gtk_text_attributes_ref: assertion 'values != NULL' failed
(fileChooser.py:40834): Gtk-CRITICAL **: gtk_text_attributes_ref: assertion 'values != NULL' failed
(fileChooser.py:40834): Pango-CRITICAL **: pango_layout_new: assertion 'context != NULL' failed
Segmentation fault (core dumped)
#!/usr/bin/env python
import os
import re
import multiprocessing
import threading
import platform
from gi.repository import Gtk, GLib, Gdk, GObject
class ANA(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.tree_store = dict()
self.COL_NAME = 0
self.COL_COLOR = 1
self.window = Gtk.Window()
self.window.set_title("Analysing Results")
self.window.set_size_request(1000, 750)
self.connect('destroy', lambda *w: Gtk.main_quit())
self.main_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
self.window.add(self.main_vbox)
self.hpaned = Gtk.HPaned()
self.hpaned.set_position(295)
self.main_vbox.pack_start(self.hpaned, True, True, 0)
self.notebook = Gtk.Notebook()
for tab in ['A', 'B']:
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
self._new_notebook_page(self.notebook, scrolled_window, tab)
treeview = self.__create_treeview(tab)
scrolled_window.add(treeview)
self.hpaned.add(self.notebook)
self.notebook1 = Gtk.Notebook()
self.hpaned.add(self.notebook1)
self.scrolled_window2, self.info_buffer, self.info_text_view = self.__create_text(True)
self._new_notebook_page(self.notebook1, self.scrolled_window2, '_Info')
info_text_view = self.info_text_view
self.window.show_all()
def _new_notebook_page(self, notebook, widget, label):
l = Gtk.Label(label='')
l.set_text_with_mnemonic(label)
notebook.append_page(widget, l)
def __create_text(self, is_source=False):
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
text_view = Gtk.TextView()
scrolled_window.add(text_view)
buffer = Gtk.TextBuffer()
text_view.set_buffer(buffer)
text_view.set_editable(False)
text_view.set_cursor_visible(True)
return scrolled_window, buffer, text_view
def __create_treeview(self, tab_name):
treestore = Gtk.TreeStore(str, str)
self.tree_store[tab_name] = treestore
treeview = Gtk.TreeView(treestore)
selection = treeview.get_selection()
selection.set_mode(Gtk.SelectionMode.BROWSE)
treeview.set_size_request(200, -1)
cell = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(tab_name, cell, foreground=self.COL_COLOR)
column.add_attribute(cell, "text", self.COL_NAME)
treeview.append_column(column)
if tab_name == "A":
selection.connect('changed', self.selection_changed_A)
elif tab_name == "B":
selection.connect('changed', self.selection_changed_B)
treeview.expand_all()
return treeview
def selection_changed_A(self):
print "A"
def selection_changed_B(self):
print "B"
class ANALYSING_PROCESS(multiprocessing.Process):
def __init__(self):
super(ANALYSING_PROCESS, self).__init__()
def run(self):
import time
time.sleep(5)
ANA()
class ANALYSING_THREAD(threading.Thread):
def __init__(self, pbar, timer):
super(ANALYSING_THREAD, self).__init__()
self.pbar = pbar
self.timer = timer
def run(self):
Gdk.threads_init()
Gdk.threads_enter()
import time
time.sleep(5)
ANA()
Gdk.threads_leave()
self.pbar.set_text("Done")
self.pbar.set_show_text(True)
GObject.source_remove(self.timer)
class File_Chooser(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect('destroy', lambda *w: Gtk.main_quit())
self.set_title("Test")
self.set_border_width(8)
frame = Gtk.Frame()
self.add(frame)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
self.vbox.set_border_width(8)
frame.add(self.vbox)
label = Gtk.Label()
label.set_markup("<span font_desc=\"Serif 25\" foreground=\"#015F85\" size=\"x-large\"> Test</span>")
self.vbox.pack_start(label, False, False, 0)
self.button_entry = dict()
self.entry_name = dict()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
button = Gtk.Button("Browse Files")
button.connect('clicked', self.browse_files)
hbox.pack_start(button, False, False, 0)
label = Gtk.Label()
label.set_markup("<span foreground=\"#015F85\"> files </span>")
label.set_use_underline(True)
hbox.pack_start(label, False, False, 0)
self.entry1 = Gtk.Entry()
hbox.pack_start(self.entry1, True, True, 0)
label.set_mnemonic_widget(self.entry1)
self.button_entry[button] = self.entry1
self.entry_name['files'] = self.entry1
self.vbox.pack_start(hbox, False, False, 0)
separator = Gtk.HSeparator()
self.vbox.pack_start(separator, False, False, 1)
alignment1 = Gtk.Alignment()
alignment1.set_halign(Gtk.Align.CENTER)
self.vbox.pack_start(alignment1, False, False, 1)
self.pbar = Gtk.ProgressBar()
alignment1.add(self.pbar)
self.pbar.set_text("Not Run")
self.pbar.set_show_text(True)
hbox2 = Gtk.HBox(False, 2)
self.vbox.pack_start(hbox2, False, False, 1)
button3 = Gtk.Button("Analyze")
button3.connect('clicked', self.tar_File_analyze)
hbox2.pack_end(button3, False, False, 1)
button4 = Gtk.Button("close")
button4.connect('clicked', self.__quit)
hbox2.pack_end(button4, False, False, 1)
self.show_all()
def browse_files(self, button):
dialog = Gtk.FileChooserDialog("Please choose a file", self,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
filter = Gtk.FileFilter()
filter.set_name("Tar files")
filter.add_pattern("*.tar")
filter.add_pattern("*.rar")
filter.add_pattern("*.tar.gz")
dialog.add_filter(filter)
filter = Gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dialog.add_filter(filter)
filter = Gtk.FileFilter()
filter.set_name("Images")
filter.add_mime_type("image/png")
filter.add_mime_type("image/jpeg")
filter.add_mime_type("image/gif")
filter.add_pattern("*.png")
filter.add_pattern("*.jpg")
filter.add_pattern("*.gif")
filter.add_pattern("*.tif")
filter.add_pattern("*.xpm")
dialog.add_filter(filter)
response = dialog.run()
if response == Gtk.ResponseType.OK:
print dialog.get_filename(), 'selected'
self.button_entry[button].set_text(dialog.get_filename())
#entry.set_text(dialog.get_filename())
elif response == Gtk.ResponseType.CANCEL:
print 'Closed, no files selected'
dialog.destroy()
def tar_File_analyze(self, button):
#PROGRESS_THREAD(self.pbar).start()
self.pbar.set_text("Running")
self.pbar.set_show_text(True)
####self.timer = GObject.timeout_add (100, self.progress_timeout, self)
self.timer = GLib.timeout_add(100, self.progress_timeout)
t = ANALYSING_THREAD(self.pbar, self.timer)
#t = ANALYSING_PROCESS()
t.start()
def progress_timeout(self):
self.pbar.pulse()
return True
def warning(self, warnings):
dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.WARNING,
Gtk.ButtonsType.OK, "Warning!")
dialog.format_secondary_text(warnings)
response = dialog.run()
if response == Gtk.ResponseType.OK:
dialog.destroy()
def __quit(self, button):
self.destroy()
def run(self):
Gtk.main()
def main():
File_Chooser().run()
if __name__ == '__main__':
main()
Could anyone take a look at it ?
In general, GUI toolkits do not support multiple threads making toolkit calls. Usually only the initial thread is allowed to do that. Making a GUI toolkit really thread-safe is a hard problem and this is a way to avoid it.
A possible solution is to have the main thread use an idle function or timer callback to check the progress in the worker thread.
Another solution is to to the work in an external process instead of a thread. This has a number of advantages;
It makes communication explicit and tracable. GUI toolkits can generally watch e.g. a file descriptor or a socket, processing the info from it in a timeout or idle callback.
Keeping the GUI single-threaded makes locking mostly unnecessary.
And on CPython it can actually make use of multi-core machines by side-stepping the GIL.
I'm writing an application. It has a sidebar, which I want to be shut on startup. I have tried using self.sidebarbox.hide(). This only seems to work when I put it in a function that is linked to a button. When I press the button it shows/hides. How can I fix this?
Here is my code (It's written in python3 but will run in python2.):
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
hb.props.subtitle = "Digital Maths Revision Guide"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
self.sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
toplevelbox.pack_start(self.sidebarbox, False, False, 0)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
self.sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
self.sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
#This should make the sidebar hide.
self.sidebarbox.hide()
#This works. The sidebar does show/hide.
def sidebarShowHide(self, button):
if self.sidebarbox.get_visible():
self.sidebarbox.hide()
else:
self.sidebarbox.show()
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
You're calling show_all() which changes the state of all contained widgets to visible, including the sidebar.
If you still like to use it (it's convenient after all) one way is you're own method, which will hide the sidebar after showing all, e.g:
from gi.repository import Gtk, Gio
from gi.repository import WebKit
HEIGHT = 500
WIDTH = 800
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Resolution")
self.set_border_width(0)
self.set_default_size(WIDTH, HEIGHT)
hb = Gtk.HeaderBar()
hb.props.show_close_button = True
hb.props.title = "Resolution"
hb.props.subtitle = "Digital Maths Revision Guide"
self.set_titlebar(hb)
button = Gtk.Button()
icon = Gio.ThemedIcon(name="emblem-system-symbolic")
image = Gtk.Image.new_from_gicon(icon, 1)
button.add(image)
button.connect("clicked", self.sidebarShowHide)
button.set_focus_on_click(False)
hb.pack_start(button)
self.sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
toplevelbox.pack_start(self.sidebarbox, False, False, 0)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
self.sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
self.sidebarbox.pack_start(label, True, True, 0)
scroller = Gtk.ScrolledWindow()
content = WebKit.WebView()
scroller.add(content)
toplevelbox.pack_start(scroller, True, True, 0)
content.open("/home/oliver/resolution/placeholder.html")
def inital_show(self):
win.show_all()
self.sidebarbox.hide();
#This works. The sidebar does show/hide.
def sidebarShowHide(self, button):
if self.sidebarbox.get_visible():
self.sidebarbox.hide()
else:
self.sidebarbox.show()
def search_changed(self, searchentry):
pass
if __name__ == '__main__':
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.inital_show()
Gtk.main()
Note the initial_show() method, and calling it from the main section.
Imagine I want to make a simple program with GUI like this.
this is my code:
from gi.repository import Gtk
import gobject
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
Gtk.main()
def on_button_clicked(self, widget):
self.task = self.iters(100000)
gobject.idle_add(self.task.next)
def iters(self, j):
i = j
while i > 0 :
i -= 1
print i
self.progressbar.set_fraction((j - float(i)) / j)
yield True
yield False
if __name__ == '__main__':
gui = gui()
I know how to make progressbar work if I put everything in one script like that.
But, what if I want to separate gui part from logic part? So, it would be like this:
GUI.py
from gi.repository import Gtk
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
Gtk.main()
def on_button_clicked(self, widget):
//how to implement it
if __name__ == '__main__':
gui = gui()
Iteration.py
class Iteration():
def iters(self, j):
i = j
while i > 0 :
i -= 1
print i
EDIT:
One more thing, the first code above works, but why do I get this message:
/usr/lib/python2.7/dist-packages/gobject/constants.py:24: Warning: g_boxed_type_register_static: assertion `g_type_from_name (name) == 0' failed
import gobject._gobject
EDIT:
Okay, imagine I have one module like this one:
Works.py
def getImageFromInternet(uri):
#some code to get image from internet
this getImageFromInternet function is not iterable. What I want to do is processing this function in the background while updating the progressbar and doing other thing with gui. Do I need a thread for this?
Create a generator that updates the GUI and drives the underlying data model generator, and pass that to idle_add. For example (untested):
def on_button_clicked(self, widget):
cnt = 10000
task = self.iters(cnt)
def gui_iter():
for i, ignore in enumerate(task, 1):
self.progressbar.set_fraction(i / cnt)
yield True
yield False
gobject.idle_add(gui_iter().next)
im trying to get drag and drop working well in pygobject, but it is slow and unresponsive, 90% of the time i have to wave the item i am dragging around before i can drop it successfully, can anyone see if i am doing it incorrectly or is this a bug with pygobject? here is my code
from gi.repository import Gtk, GdkPixbuf, Gdk
import os
def got_data_cb(windowid, context, x, y, data, info, time):
# Got data.
tempArray = data.get_text().splitlines()
for i in tempArray:
i = i.replace('file://','')
print i
windowid.get_model().append([i])
context.finish(True, False, time)
def drop_cb(windowid, context, x, y, time):
# Some data was dropped, get the data
windowid.drag_get_data(context, context.list_targets()[-1], time)
return True
def main():
win = Gtk.Window()
win.connect('destroy', lambda x: Gtk.main_quit())
win.set_default_size(450, 400)
amodel = Gtk.ListStore(str)
column = Gtk.TreeViewColumn()
title = Gtk.CellRendererText()
column.pack_start(title, True)
column.add_attribute(title, "text", 0)
atree = Gtk.TreeView(amodel)
atree.append_column(column)
builder = Gtk.Builder()
filename = os.path.join('', 'treeview.ui')
builder.add_from_file(filename)
abox = builder.get_object('treeview1')
atree.drag_dest_set(0, [], 0)
atree.connect('drag_motion', lambda v,w,x,y,z: True)
atree.connect('drag_drop', drop_cb)
atree.connect('drag_data_received', got_data_cb)
win.add(atree)
win.show_all()
if __name__ == '__main__':
Gtk.main()
main()
Because I haven't "treeview.ui" file, you referenced, I port the drag'n'drop treeview example of pygtk.
This might be also an example on how to convert old pygtk code to pygi. I only test this code with python3.
#!/usr/bin/env python
# example treeviewdnd.py
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)
# 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):
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):
model = treeview.get_model()
data = selection.get_data().decode("utf-8")
drop_info = treeview.get_dest_row_at_pos(x, y)
if drop_info:
path, position = drop_info
iter = model.get_iter(path)
if (position == Gtk.TreeViewDropPosition.BEFORE
or position == Gtk.TreeViewDropPosition.BEFORE):
model.insert_before(iter, [data])
else:
model.insert_after(iter, [data])
else:
model.append([data])
if context.get_actions() == Gdk.DragAction.MOVE:
context.finish(True, True, etime)
return
def main():
Gtk.main()
if __name__ == "__main__":
treeviewdndex = TreeViewDnDExample()
main()
In order for me to get drag n drop working from another desktop app to my app, I had to add a drag_motion_callback to copy the data into the context:
Class Window(Gtk.Window):
def __init__(self):
#other stuff before here
#Set up dragNdrop to add URIs to open draw
self.connect("drag-motion", self.motion_cb)
self.connect("drag-drop", self.drop_cb)
self.connect("drag-data-received", self.got_data_cb)
self.drag_dest_set(0, [], 0)
def motion_cb(self, wid, context, x, y, time):
Gdk.drag_status(context,Gdk.DragAction.COPY, time)
# Returning True which means "I accept this data".
return True
def drop_cb(self, wid, context, x, y, time):
wid.drag_get_data(context, context.list_targets()[-1], time)
def got_data_cb(self, wid, context, x, y, data, info, time):
#Need to do something here
files=data.get_text().rstrip('\n').split('\n')
for fn in files:
fn= fn.split('file://',1)[-1]
self.add_file(fn)
self.place_items()
print files
context.finish(True, False, time)