Having trouble understanding how to manually (I'm not using timeouts at this stage) refresh a window, or part of a window in PyGTK, version 2.
I want to display some information, in this example, a selection of output from the "df" command, and then be able to manually refresh the window, using a "refresh" button. I've looked at various examples and the PyGTK tutorial, but the exact place to put the refresh code escapes me. Tried using queue_draw in the "freedisk" function, in another function within that, in the "main" loop, without success.
I appreciate GTK3 is the preferred version these days, but I'd rather get this right, before updating.
The code for "freedisk":
#!/usr/bin/env python
import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk
def yield_lines(data):
for line in data.split("\n"):
yield line
def line_to_list(line):
return re.sub(" +", " ", line).split()
def remov_percent(col):
return re.sub("%", "", col)
class freedisk:
def getdiskfree(self):
diskfreecmd = ['/usr/bin/df', '-hlT', '-x', 'tmpfs']
diskfree = subprocess.Popen(diskfreecmd, stdout=subprocess.PIPE).communicate()[0]
return diskfree
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("delete_event", self.delete_event)
box1 = gtk.VBox(False, 10)
box1a = gtk.HBox(False, 0)
box2 = gtk.VBox(False, 10)
box3 = gtk.HBox(False, 0)
frame_1 = gtk.Frame()
window.add(box1)
diskfreedata = self.getdiskfree()
diskfreedata = diskfreedata.replace("Mounted on", "Mounted_on")
lines = yield_lines(diskfreedata)
headers = line_to_list(lines.next())
columns = [list() for i in range(len(headers))]
for i,h in enumerate(headers):
columns[i].append(h)
for line in lines:
for i,l in enumerate(line_to_list(line)):
columns[i].append(l)
j=0
for i in columns[0]:
j += 1
title = gtk.Label('Disk usage and free space')
box1.pack_start(title, False, False, 10)
box1.pack_start(box1a, True, True, 0)
box1a.pack_start(frame_1, True, True, 20)
frame_1.add(box2)
ucdiskfreedata = unicode(diskfreedata)
label = gtk.Label(diskfreedata)
label.set_line_wrap(False)
label.set_max_width_chars(80)
label.modify_font(pango.FontDescription("monospace"))
box_sp1 = gtk.HBox(False, 0)
box_sp2 = gtk.HBox(False, 0)
refresh_button = gtk.Button("Refresh")
close_button = gtk.Button("Close")
close_button.connect("clicked", self.delete_event, "quit")
mntlabel = [list() for i in range(j)]
sizelabel = [list() for i in range(j)]
progbar = [list() for i in range(j)]
freelabel = [list() for i in range(j)]
perlabel = [list() for i in range(j)]
rows = [list() for i in range(j)]
box2.pack_start(box_sp1, False, False, 0)
rows[0] = gtk.HBox(True, 0)
box2.pack_start(rows[0], False, False, 5)
mntlabel[0] = gtk.Label(columns[6][0])
freelabel[0] = gtk.Label(columns[4][0])
sizelabel[0] = gtk.Label(columns[2][0])
blank = gtk.Label(columns[5][0])
rows[0].pack_start(mntlabel[0], False, False, 0)
rows[0].pack_start(sizelabel[0], False, False, 0)
rows[0].pack_start(blank, False, False, 0)
rows[0].pack_start(freelabel[0], False, False, 0)
for i in range(1,j):
x = remov_percent(columns[5][i])
y = decimal.Decimal(x) / decimal.Decimal('100')
mntlabel[i] = gtk.Label(columns[6][i])
mntlabel[i].set_justify(gtk.JUSTIFY_RIGHT)
freelabel[i] = gtk.Label(columns[4][i])
sizelabel[i] = gtk.Label(columns[2][i])
progbar[i] = gtk.ProgressBar()
gtk.ProgressBar.set_fraction(progbar[i], y)
progbar[i].set_text(str(columns[5][i]))
rows[i] = gtk.HBox(True, 0)
rows[i].pack_start(mntlabel[i], False, False, 0)
rows[i].pack_start(sizelabel[i], False, False, 0)
rows[i].pack_start(progbar[i], False, False, 0)
rows[i].pack_start(freelabel[i], False, False, 0)
box2.pack_start(rows[i], False, False, 0)
box2.pack_start(box_sp2, False, False, 10)
box3.pack_end(close_button, False, False, 20)
box3.pack_end(refresh_button, False, False, 20)
box1.pack_start(box3, False, False, 10)
box1.show()
box1a.show()
box2.show()
box_sp1.show()
box_sp2.show()
frame_1.show()
title.show()
mntlabel[0].show()
blank.show()
for i in range(0, j):
rows[i].show()
mntlabel[i].show()
sizelabel[i].show()
freelabel[i].show()
for i in range(1,j):
progbar[i].show()
refresh_button.show()
close_button.show()
box3.show()
window.show()
def main():
gtk.main()
if __name__ == "__main__":
freedisk()
main()
Edited (24.10.17) to add a simpler example then, just show the outputs of the command "ls":
#!/usr/bin/env python
import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk
class PyGlist:
def getlisting(self):
listingcmd = ['ls', '-1']
listing = subprocess.Popen(listingcmd, stdout=subprocess.PIPE).communicate()[0]
return listing
def delete_event(self, widget, event, data=None):
gtk.main_quit()
return False
def destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
# nothing here
return None
def processlisting(self):
listingdata = self.getlisting()
print (listingdata)
loclabel = gtk.Label(listingdata)
loclabel.set_line_wrap(False)
loclabel.set_max_width_chars(80)
loclabel.modify_font(pango.FontDescription("monospace"))
return loclabel
def refresh(self, widget, data):
widget = self.processlisting()
widget.queue_draw()
return
def main(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("delete_event", self.delete_event)
box1 = gtk.VBox(False, 10)
box1a = gtk.HBox(False, 0)
box2 = gtk.VBox(False, 10)
box3 = gtk.HBox(False, 0)
frame_1 = gtk.Frame()
window.add(box1)
title = gtk.Label('Listing')
box1.pack_start(title, False, False, 10)
box1.pack_start(box1a, True, True, 0)
box1a.pack_start(frame_1, True, True, 20)
frame_1.add(box2)
label = self.processlisting()
box_sp1 = gtk.HBox(False, 0)
box_sp2 = gtk.HBox(False, 0)
box2.pack_start(label, False, False, 0)
refresh_button = gtk.Button("Refresh")
refresh_button.connect("clicked", self.refresh, label)
close_button = gtk.Button("Close")
close_button.connect("clicked", self.delete_event, "quit")
box3.pack_end(close_button, False, False, 20)
box3.pack_end(refresh_button, False, False, 20)
box1.pack_start(box3, False, False, 10)
box1.show()
box1a.show()
label.show()
box2.show()
box_sp1.show()
box_sp2.show()
frame_1.show()
title.show()
refresh_button.show()
close_button.show()
box3.show()
window.show()
gtk.main()
if __name__ == "__main__":
pyglist =PyGlist()
pyglist.main()
I'm getting closer to understanding now what's happening; I'm just slow at picking up concepts.
That's because in processlisting you create a new label each time, but you never add it to the widget tree, so it is never displayed. What you should do is reuse the label you already added in the user interface, and modify that one. Just pass it as a parameter when you connect to the clicked signal of the refresh button.
Also, no need to call show on each widget, just call show_all on the toplevel gtk window.
Finally, you only need to connect to the destroy signal to call gtk_main_quit. delete-event is when you want to intercept the user wanting to close the window and want to change the default behavior.
#!/usr/bin/env python
import pango, pygtk, subprocess, re, string, decimal, time
pygtk.require('2.0')
import gtk
class PyGlist:
def getlisting(self):
listingcmd = ['ls', '-1']
listing = subprocess.Popen(listingcmd, stdout=subprocess.PIPE).communicate()[0]
print listing
return listing
def on_destroy(self, widget, data=None):
gtk.main_quit()
def refresh(self, refresh_button, label):
label.set_text(self.getlisting())
def main(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("destroy", self.on_destroy)
box1 = gtk.VBox(False, 10)
box1a = gtk.HBox(False, 0)
box2 = gtk.VBox(False, 10)
box3 = gtk.HBox(False, 0)
frame_1 = gtk.Frame()
window.add(box1)
title = gtk.Label('Listing')
box1.pack_start(title, False, False, 10)
box1.pack_start(box1a, True, True, 0)
box1a.pack_start(frame_1, True, True, 20)
frame_1.add(box2)
label = gtk.Label(self.getlisting())
label.set_line_wrap(False)
label.set_max_width_chars(80)
label.modify_font(pango.FontDescription("monospace"))
box_sp1 = gtk.HBox(False, 0)
box_sp2 = gtk.HBox(False, 0)
box2.pack_start(label, False, False, 0)
refresh_button = gtk.Button("Refresh")
refresh_button.connect("clicked", self.refresh, label)
close_button = gtk.Button("Close")
close_button.connect("clicked", self.on_destroy)
box3.pack_end(close_button, False, False, 20)
box3.pack_end(refresh_button, False, False, 20)
box1.pack_start(box3, False, False, 10)
window.show_all()
gtk.main()
if __name__ == "__main__":
pyglist =PyGlist()
pyglist.main()
I've cracked it, finally. Thanks to the help of the posters above.
The simpler example showed me where I was overcomplicating things.
The original program "freedisk" I finally got working, by moving more code into a separate function which made it easier to see what was happening.
Basically, the aim was to take the output of "df" and tweak it slightly with a hybrid text and graphical display.
Aside from any formatting boxes, titles, etc, there would be a VBox container with one HBox per line of "df" output, recreating some of the columnar output in text form, but with one column of progressbars.
The data translation and creation of rows I moved into a separate function.
This would be called initially, and then each time a "refresh" button were pressed.
Any existing rows inside the vertical box would be destroyed before the data was recalculated and then re-output. And this was where the final piece of the puzzle fell into place.
After destroying the widgets, and replacing them, I'd not realised they had to be re-"show"n. Adding one final line "widget.show_all()" solved the problem.
Related
I am trying to dynamically add an element to a ListBox.
It works without a function but not with.
Works
rootbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
button = Gtk.Button(label="ok")
listbox = Gtk.ListBox()
el = Gtk.ListBoxRow()
label = Gtk.Label('Element 0')
el.add(label)
listbox.add(el)
button.connect("clicked", addList)
rootbox.pack_start(button, False, True, 0)
rootbox.pack_start(listbox, True, True, 0)
window.add(rootbox)
Does not work (it prints 'ok' but doesn't add the element)
# -------------------
def addList(b):
print('ok')
global listbox
el = Gtk.ListBoxRow()
label = Gtk.Label('Element 0')
listbox.add(el)
# -------------------
rootbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
button = Gtk.Button(label="ok")
listbox = Gtk.ListBox()
button.connect("clicked", addList)
rootbox.pack_start(button, False, True, 0)
rootbox.pack_start(listbox, True, True, 0)
window.add(rootbox)
# -------------------------------------------
Thanks in advance
window.show_all() needed at the end of the addList function ! Hope it helps
after I change widget state to disabled. view of widget is changing to disabled view. I don't want to change view of widget only change state of widget. How can I ensure this ?
thanks.
btn = Gtk.Button("example")
btn.set_sensitive(False) # this code makes button disabled.
btn.set_view("normal") # I know set_view method does not exist but is there a method like this to change disabled view to normal view.
my full code
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class TitledEntry(Gtk.VBox):
def __init__(self, title=None, text=""):
Gtk.VBox.__init__(self, spacing=2)
title = Gtk.Label(label=title, halign=Gtk.Align.START)
self.add(title)
entry = Gtk.Entry(text=text)
self.add(entry)
self.title_label = title
self.entry = entry
self.show_all()
class AgeBox(Gtk.HBox):
def __init__(self, age=0):
Gtk.HBox.__init__(self, halign=Gtk.Align.START)
lb = Gtk.Label("Age : ")
self.add(lb)
agebutton = Gtk.SpinButton(adjustment=Gtk.Adjustment(age, 0, 1000, 1, 10, 0),
numeric=True, update_policy=Gtk.SpinButtonUpdatePolicy.IF_VALID)
agebutton.set_value(age)
self.add(agebutton)
self.agebutton = agebutton
class HumanTemp(Gtk.VBox):
def __init__(self, nick="", age=0, country="", language=""):
Gtk.VBox.__init__(self, spacing=3, border_width=5, halign=Gtk.Align.CENTER)
temp_name = Gtk.Label()
temp_name.set_markup("<span font_weight='bold'>Human</span>")
self.pack_start(temp_name, False, False, 0)
nick_box = TitledEntry("Nick", nick)
self.pack_start(nick_box, False, False, 0)
age_box = AgeBox(age)
self.pack_start(age_box, False, False, 0)
country_box = TitledEntry("Country", country)
self.pack_start(country_box, False, False, 0)
language_box = TitledEntry("Language", language)
self.pack_start(language_box, False, False, 0)
self.show_all()
class AnimTemp(Gtk.VBox):
def __init__(self, nick="", age=0, kind="wolf"):
Gtk.VBox.__init__(self, spacing=3, border_width=5, halign=Gtk.Align.CENTER)
temp_name = Gtk.Label()
temp_name.set_markup("<span font_weight='bold'>Animal</span>")
self.pack_start(temp_name, False, False, 0)
nick_box = TitledEntry("Nick", nick)
self.pack_start(nick_box, False, False, 0)
age_box = AgeBox(age)
self.pack_start(age_box, False, False, 0)
kind_box = Gtk.VBox()
self.pack_start(kind_box, False, False, 0)
kind_name = Gtk.Label("Kind", halign=Gtk.Align.START)
kind_box.pack_start(kind_name, False, False, 0)
box = Gtk.HBox()
kind_box.pack_start(box, False, False, 0)
wolf = Gtk.RadioButton("Wolf",group=None)
box.pack_start(wolf, False, False, 0)
tiger = Gtk.RadioButton("Tiger", group=wolf)
box.pack_start(tiger, False, False, 0)
if kind == "wolf":
wolf.set_active(True)
else:
tiger.set_active(True)
self.show_all()
class ElfTemp(Gtk.VBox):
def __init__(self, nick="", age=0, clan="terran", race="night"):
Gtk.VBox.__init__(self, spacing=3, border_width=5, halign=Gtk.Align.CENTER)
temp_name = Gtk.Label()
temp_name.set_markup("<span font_weight='bold'>Elf</span>")
self.pack_start(temp_name, False, False, 0)
nick_box = TitledEntry("Nick", nick)
self.pack_start(nick_box, False, False, 0)
age_box = AgeBox(age)
self.pack_start(age_box, False, False, 0)
clan_box = Gtk.VBox(halign=Gtk.Align.START)
self.pack_start(clan_box, False, False, 0)
clan_name = Gtk.Label("Clan", halign=Gtk.Align.START)
clan_box.pack_start(clan_name, False, False, 0)
box = Gtk.HBox()
clan_box.pack_start(box, False, False, 0)
terran = Gtk.RadioButton("Terran",group=None)
box.pack_start(terran, False, False, 0)
vanu = Gtk.RadioButton("Vanu", group=terran)
box.pack_start(vanu, False, False, 0)
atlas = Gtk.RadioButton("Atlas", group=terran, halign=Gtk.Align.CENTER)
clan_box.pack_start(atlas, False, False, 0)
race_box = Gtk.VBox()
self.pack_start(race_box, False, False, 0)
race_name = Gtk.Label("Race", halign=Gtk.Align.START)
race_box.pack_start(race_name, False, False, 0)
box = Gtk.HBox()
race_box.pack_start(box, False, False, 0)
night = Gtk.RadioButton("Night", group=None)
box.pack_start(night, False, False, 0)
blood = Gtk.RadioButton("Blood", group=night)
box.pack_start(blood, False, False, 0)
if clan == "terran":
terran.set_active(True)
elif clan == "vanu":
vanu.set_active(True)
else:
atlas.set_active(True)
if race == "night":
night.set_active(True)
else:
blood.set_active(True)
self.show_all()
class SelectTemplateWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Select a Temlpate")
self.resize(581, 506)
scw = Gtk.ScrolledWindow(visible=True)
self.add(scw)
flbox = Gtk.FlowBox(min_children_per_line=2, valign=Gtk.Align.START)
scw.add(flbox)
keltas = ElfTemp("Keltas", 24, "terran", "blood")
flbox.add(keltas)
illidan = ElfTemp("Illidan", 47, "vanu", "night")
flbox.add(illidan)
jack = HumanTemp("Jack", 21, "Canada", "English")
flbox.add(jack)
santiago = HumanTemp("Santiago", 37, "Spain", "Spanish")
flbox.add(santiago)
moon_wolf = AnimTemp("Moon Wolf", 941, "wolf")
flbox.add(moon_wolf)
lexar = AnimTemp("Lexar", 438, "tiger")
flbox.add(lexar)
flbox.show_all()
win = SelectTemplateWindow()
win.connect("delete-event", Gtk.main_quit)
win.show()
Gtk.main()
I want to no editable FlowBoxChild (template) but when I set sensitive to False, the view is changing (being bad view). how can I do this without setting sensitive to False
No sure this is what you are after, but a workaround is to pack the button inside an event box and then toggle the above_child property to get that desired result. The button will be inhibited from emitting signals when the event box is above the button and will emit signals otherwise.
Here is a simple example:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.button1 = Gtk.ToggleButton(label="Sensitive")
self.button1.connect("clicked", self.on_button1_clicked)
self.box.pack_start(self.button1, True, True, 0)
self.evbox = Gtk.EventBox()
self.button2 = Gtk.Button(label="Goodbye")
self.button2.connect("clicked", self.on_button2_clicked)
self.evbox.add(self.button2)
self.evbox.set_above_child(True)
self.box.pack_start(self.evbox, True, True, 0)
def on_button1_clicked(self, widget):
self.evbox.set_above_child(not self.button1.get_active())
def on_button2_clicked(self, widget):
print("Goodbye")
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
The Sensitive toggle button, will control the button on the right while keeping its appearance even when "not sensitive". In fact you are just controlling the event box property.
Pack the button inside an event box:
...
self.evbox = Gtk.EventBox()
self.button2 = Gtk.Button(label="Goodbye")
self.evbox.add(self.button2)
self.evbox.set_above_child(True) # Default is not sensitive
...
To be consistent with the toggle button, the default is setting the button as not sensitive, then on the toggle button callback, we change the event box property, which is equivalent to the logical negation of the toggle property of the toggle button:
def on_button1_clicked(self, widget):
self.evbox.set_above_child(not self.button1.get_active())
Using this solution, would be as simple as invoking a single method, set_above_child, on the button's parent container.
I'm working on a simple GUI application using PyGObject and GTK+ 3. In this case, I'm wanting to have a button which brings up a dialog box that when you click OK will add an item to a list. I have that part working but the final part that doesn't work is adding the item to the list. It appears that an item does get added but it's empty. It's selectable, though, just very small. I've tried adding other kinds of widgets like Gtk.Button to see if it was something weird with Gtk.Label. When I add the Gtk.Label in the constructor it works just fine.
Also I know this isn't quite the way to do things and there are some oddities with how I'm doing stuff in my code but I'm still just learning how to use PyGObject/GTK+ 3. I imagine this problem is just something stupid I'm overlooking.
MainWindow.py
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import PromptDialog
class MainWindow(Gtk.Window):
def addURLResponse(self, dialog, response, listBox):
if(response == Gtk.ResponseType.OK):
print(dialog.get_text())
label = Gtk.Label(dialog.get_text())
print(label.get_text())
listBox.add(label)
if(response != Gtk.ResponseType.DELETE_EVENT):
dialog.destroy()
def addURL(self, button):
URLDialog = PromptDialog.PromptDialog("Add URL", self)
URLDialog.connect('response', self.addURLResponse, button.get_parent().get_parent().get_parent().get_children()[1])
URLDialog.show_all()
def __init__(self):
Gtk.Window.__init__(self, title="MPV-VJ")
self.playlistsBar = Gtk.FlowBox()
self.newBtn = Gtk.Button.new_with_label('+')
self.playlistsBar.add(self.newBtn)
self.playlistsList = Gtk.ListBox()
self.playlistsView = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
self.playlistsView.pack_start(self.playlistsBar, False, False, 0)
self.playlistsView.pack_start(self.playlistsList, True, True, 0)
self.playlist1View = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
self.playlist1Bar = Gtk.FlowBox()
self.addUrl1Btn = Gtk.Button.new_with_label('+URL')
self.addUrl1Btn.connect('clicked', self.addURL)
self.playlist1Bar.add(self.addUrl1Btn)
self.addFile1Btn = Gtk.Button.new_with_label('+file')
self.playlist1Bar.add(self.addFile1Btn)
self.addDir1Btn = Gtk.Button.new_with_label('+dir')
self.playlist1Bar.add(self.addDir1Btn)
self.playlist1List = Gtk.ListBox()
self.playlist1View.pack_start(self.playlist1Bar, False, False, 0)
self.playlist1View.pack_start(self.playlist1List, True, True, 0)
self.playlist2View = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
self.playlist2Bar = Gtk.FlowBox()
self.addUrl2Btn = Gtk.Button.new_with_label('+URL')
self.playlist2Bar.add(self.addUrl2Btn)
self.addFile2Btn = Gtk.Button.new_with_label('+file')
self.playlist2Bar.add(self.addFile2Btn)
self.addDir2Btn = Gtk.Button.new_with_label('+dir')
self.playlist2Bar.add(self.addDir2Btn)
self.playlist2List = Gtk.ListBox()
self.playlist2View.pack_start(self.playlist2Bar, False, False, 0)
self.playlist2View.pack_start(self.playlist2List, True, True, 0)
self.plViewsBox = Gtk.HPaned()
self.plViewsBox.pack1(self.playlist1View, True, False)
self.plViewsBox.pack2(self.playlist2View, True, False)
self.viewBox = Gtk.HPaned()
self.viewBox.pack1(self.playlistsView, True, False)
self.viewBox.pack2(self.plViewsBox, True, False)
self.viewBox.set_position(200)
self.logView = Gtk.ListBox()
self.contentBox = Gtk.VPaned()
self.contentBox.pack1(self.viewBox, True, False)
self.contentBox.pack2(self.logView, True, False)
self.contentBox.set_position(400)
self.toolBar = Gtk.FlowBox()
self.newBtn = Gtk.Button.new_with_label('new')
self.toolBar.add(self.newBtn)
self.loadBtn = Gtk.Button.new_with_label('load')
self.toolBar.add(self.loadBtn)
self.saveBtn = Gtk.Button.new_with_label('save')
self.toolBar.add(self.saveBtn)
self.mainBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
self.mainBox.pack_start(self.toolBar, False, False, 0)
self.mainBox.pack_start(self.contentBox, True, True, 0)
self.add(self.mainBox)
self.resize(1000, 500)
PromptDialog.py
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class PromptDialog(Gtk.Dialog):
def get_text(self):
return(self.entry.get_buffer().get_text())
def __init__(self, message, mainWindow):
Gtk.Dialog.__init__(self, title="Prompt")
self.set_modal(True)
self.set_transient_for(mainWindow)
self.label = Gtk.Label(message)
self.entry = Gtk.Entry()
self.get_content_area().pack_start(self.label, True, True, 0)
self.get_content_area().pack_start(self.entry, True, True, 0)
self.add_button("OK", Gtk.ResponseType.OK)
self.add_button("Cancel", Gtk.ResponseType.CANCEL)
The widget added to the window needs to have its .show() method called before it'll appear.
I'm writing an app using Gtk3 and Python. I have a revealer as a sidebar to select the content and a webkit webview to display the main content. When the revealer is hidden the webview doesn't fill the entire window space and I don't know why. Any help would be appreciated.
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"
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)
sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
self.sidebar = Gtk.Revealer()
self.sidebar.set_transition_duration(0)
self.sidebar.set_reveal_child(False)
toplevelbox.pack_start(self.sidebar, False, False, 0)
self.sidebar.add(sidebarbox)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
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 sidebarShowHide(self, button):
if self.sidebar.get_reveal_child():
self.sidebar.set_reveal_child(False)
else:
self.sidebar.set_reveal_child(True)
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Well, i have done some GtkRevealer few months ago and it works. It drive me nuts to see this piece of code was not.
I opened my project again and look inside where that part is, and it turn out the toplevel container where the Gtk.Revealer resides, has to has Gtk.Orientation.VERTICAL.. if you change your "toplevelbox" orientation to that, it will work, but it wont be sidebar. It will coming from top or bottom. It goes the same if you change GtkBox with GtkGrid. If I were to guess it depends on the children default orientation.
Workaround on that, is to use widget hide/show mechanism (believe me, i ransack your code and it works).
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"
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)
sidebarbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
toplevelbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(toplevelbox)
self.sidebar = Gtk.Box()
toplevelbox.pack_start(self.sidebar, False, False, 0)
self.sidebar.add(sidebarbox)
self.searchentry = Gtk.SearchEntry()
self.searchentry.connect("search-changed", self.search_changed)
sidebarbox.pack_start(self.searchentry, False, False, 0)
label = Gtk.Label("Contents Selector")
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 sidebarShowHide(self, button):
if self.sidebar.get_visible():
self.sidebar.hide ()
else:
self.sidebar.show ()
def search_changed(self, searchentry):
pass
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
This smells like a bug.
As a workaround, you could use
def sidebarShowHide(self, button):
self.sidebarbox.set_visible(not self.sidebarbox.get_visible())
but this does not yield any transition animation, but does remove its allocated space for the time being invisible.
Actually the C demo provided within the git repo resizes as expected, so this might in fact have to do something with the child widgets prefered orientation.
I'm trying to write a script that will do check-box invisible when i click on main check-box.
This is code which i have written for that
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, cairo, gio, pango, pangocairo, atk, gobject
class form:
def typeentry(self, widget, data):
if data=="num" and widget.get_active()==True:
self.buttonI.set_visible(True)
self.buttonS.set_visible(True)
self.buttonF.set_visible(True)
self.buttonL.set_visible(True)
if data=="num" and widget.get_active()==False:
self.buttonI.set_visible(False)
self.buttonS.set_visible(False)
self.buttonF.set_visible(False)
self.buttonL.set_visible(False)
def __init__(self):
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.win.set_position(gtk.WIN_POS_CENTER)
self.win.set_size_request(530, 340)
self.win.set_resizable(False)
evbox = gtk.VBox(False, 0)
frame = gtk.AspectFrame("Select", 1.0, 1.0,3, False)
frame.set_border_width(10)
vbox = gtk.VBox(False, 5)
vbox.set_border_width(5)
frame.add(vbox)
vbox.set_uposition(90,165)
button = gtk.CheckButton("Number")
button.connect("toggled", self.typeentry, "num")
vbox.pack_start(button, False, False, 2)
button.set_active(True)
button = gtk.CheckButton("String")
vbox.pack_start(button, False, False, 0)
button.set_active(True)
self.buttonI = gtk.CheckButton("int")
self.buttonI.connect("toggled", self.typeentry, "int")
vbox.pack_start(self.buttonI, False, False, 0)
self.buttonI.set_active(True)
self.buttonI.set_uposition(300,155)
self.buttonF = gtk.CheckButton("float")
self.buttonF.connect("toggled", self.typeentry, "float")
vbox.pack_start(self.buttonF, False, False, 0)
self.buttonF.set_active(True)
self.buttonF.set_uposition(300,170)
self.buttonL = gtk.CheckButton("long")
self.buttonL.connect("toggled", self.typeentry, "long")
vbox.pack_start(self.buttonL, False, False, 0)
self.buttonL.set_active(True)
self.buttonL.set_uposition(300,185)
self.buttonS = gtk.CheckButton("short")
self.buttonS.connect("toggled", self.typeentry, "short")
vbox.pack_start(self.buttonS, False, False, 0)
self.buttonS.set_active(True)
self.buttonS.set_uposition(300,200)
evbox.add(frame)
self.win.add(evbox)
hbox = gtk.HBox(False, 0)
evbox.pack_start(hbox, False, True, 5)
hbox.set_uposition(0,295)
button = gtk.Button("Previous")
button.connect("clicked", lambda w: gtk.main_quit())
button.set_size_request(90,35)
hbox.pack_start(button, False, False,10)
dbox = gtk.HBox(False, 0)
button = gtk.Button("Next")
button.connect("clicked", lambda w: gtk.main_quit())
button.set_size_request(90,35)
dbox.pack_end(button, True, True, 5)
button = gtk.Button("Exit")
button.set_size_request(90,35)
dbox.pack_end(button, True, True,5)
hbox.pack_end(dbox, False,True, 5)
self.win.show_all()
def main(self):
gtk.main()
if __name__ == "__main__":
first = form()
first.main()
the code is running fine but at the time of running this code. it is showing below error
Traceback (most recent call last):
File "H:\Eclipse Project\Sample\test.py", line 12, in typeentry
self.buttonI.set_visible(True)
AttributeError: form instance has no attribute 'buttonI'
I am not understanding what is happening and what i do. please somebody help me for it.
Thanks
self.typeentry() gets called when you set "Number" and String" checkbutton active properties. This is before the other buttons even exist.
button = gtk.CheckButton("Number")
button.connect("toggled", self.typeentry, "num")
vbox.pack_start(button, False, False, 2)
button.set_active(True)
The call to button.set_active triggers the toogled event and thus self.typeentry is called where you try to access a member of self.buttonI and others. At this point however self.buttonI and the other buttons haven't been defined yet.
Instead add the event handler later (you don't need it while initializing):
button = gtk.CheckButton("Number")
vbox.pack_start(button, False, False, 2)
button.set_active(True)
button.connect("toggled", self.typeentry, "num")
Actually you are calling typeentry function with another checkbox button which you have defined latter on that's why it is showing error. so first you have to define all the checkbox button then you can call the function.
just see the updated code, it is running fine.
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, cairo, gio, pango, pangocairo, atk, gobject
class form:
def typeentry(self, widget, data):
print "hi"
if data=="num" and widget.get_active()==True:
self.buttonS.set_visible(True)
self.buttonI.set_visible(True)
self.buttonF.set_visible(True)
self.buttonL.set_visible(True)
if data=="num" and widget.get_active()==False:
self.buttonI.set_visible(False)
self.buttonS.set_visible(False)
self.buttonF.set_visible(False)
self.buttonL.set_visible(False)
def __init__(self):
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.win.set_position(gtk.WIN_POS_CENTER)
self.win.set_size_request(530, 340)
self.win.set_resizable(False)
evbox = gtk.VBox(False, 0)
frame = gtk.AspectFrame("Select", 1.0, 1.0,3, False)
frame.set_border_width(10)
vbox = gtk.VBox(False, 5)
vbox.set_border_width(5)
frame.add(vbox)
vbox.set_uposition(90,165)
button1 = gtk.CheckButton("Number")
vbox.pack_start(button1, False, False, 2)
button1.set_active(True)
button2 = gtk.CheckButton("String")
vbox.pack_start(button2, False, False, 0)
button2.set_active(True)
self.buttonI = gtk.CheckButton("int")
vbox.pack_start(self.buttonI, False, False, 0)
self.buttonI.set_active(True)
self.buttonI.set_uposition(300,155)
self.buttonF = gtk.CheckButton("float")
vbox.pack_start(self.buttonF, False, False, 0)
self.buttonF.set_active(True)
self.buttonF.set_uposition(300,170)
self.buttonL = gtk.CheckButton("long")
vbox.pack_start(self.buttonL, False, False, 0)
self.buttonL.set_active(True)
self.buttonL.set_uposition(300,185)
self.buttonS = gtk.CheckButton("short")
vbox.pack_start(self.buttonS, False, False, 0)
self.buttonS.set_active(True)
self.buttonS.set_uposition(300,200)
button1.connect("clicked", self.typeentry, "num")
self.buttonI.connect("clicked", self.typeentry, "int")
self.buttonF.connect("clicked", self.typeentry, "float")
self.buttonL.connect("clicked", self.typeentry, "long")
self.buttonS.connect("clicked", self.typeentry, "short")
evbox.add(frame)
self.win.add(evbox)
hbox = gtk.HBox(False, 0)
evbox.pack_start(hbox, False, True, 5)
hbox.set_uposition(0,295)
button = gtk.Button("Previous")
button.connect("clicked", lambda w: gtk.main_quit())
button.set_size_request(90,35)
hbox.pack_start(button, False, False,10)
dbox = gtk.HBox(False, 0)
button = gtk.Button("Next")
button.connect("clicked", lambda w: gtk.main_quit())
button.set_size_request(90,35)
dbox.pack_end(button, True, True, 5)
button = gtk.Button("Exit")
button.set_size_request(90,35)
dbox.pack_end(button, True, True,5)
hbox.pack_end(dbox, False,True, 5)
self.win.show_all()
def main(self):
gtk.main()
if __name__ == "__main__":
first = form()
first.main()