Neulich
Ich habe einen Tkinter-Wrapper wie IPython Notebook [Python] geschrieben
Das habe ich geschrieben. Dieses Mal werde ich, wie bereits erwähnt, dasselbe vorstellen, das auf Gtk portiert wurde. Informationen zum Anrufen finden Sie im obigen Artikel. Ich sehe die japanischen Tutorials von Gtk nicht wirklich, daher hoffe ich, dass Sie verstehen, dass die Verwendung überraschend einfach ist.
Dieses Mal ist es vollständig kompatibel mit Python3. Ich habe die print_function aus \ _ \ _ future \ _ \ _ am Anfang des Codes gebracht, aber ich brauche sie nicht, wenn ich sie als Modul aufrufe. Selbst im Test funktioniert es nur mit 3 Systemen.
Die letzte wichtige Änderung gegenüber dem IPython Notebook ist das dritte Argument beim Aufrufen der Skalierungsleiste. In der Vergangenheit war es eine Form, die Schrittgröße selbst festzulegen (Beispiel: x = (0., 10., 0.5) erstellt einen Skalierungsbalken in Schritten von 0,5 von 0,0 bis 10,0), jedoch in Abhängigkeit von Gtk Es gibt so etwas wie set_digits, und wir verwenden dies. Mit anderen Worten, dieser Teil wurde in ein Format geändert, das angibt, wie viele Stellen nach dem Dezimalpunkt verwendet werden sollen. Natürlich kann dieser Teil wie zuvor weggelassen werden, und wenn ein ganzzahliger Wert als erstes Argument angegeben wird, kann er als Ganzzahl angegeben werden, und wenn ein Bruchteil angegeben wird, sollte er bis zu 2 Stellen dauern. Es gibt. In Bezug auf die Rundung der Werte hier können Sie sehen, dass sie durch Lesen der Referenz feiner eingestellt wird, aber ich habe sie diesmal nicht manipuliert.
Daher wird der Inhalt des Schlüsselwortarguments für interaktiv wie folgt in ein Widget konvertiert.
Keyword argument | Widget |
`True` or `False` | SwitchWiget |
`value` or `(min,max)` or `(min,max,digit)` if integers are passed | IntSliderWidget |
`value` or `(min,max)` or `(min,max,digit)` if floats are passed | FloatSliderWidget |
`('orange','apple')` or `{'one':1,'two':2}` | ComboBoxWidget |
Ich habe einen Screenshot davon gemacht, wie ich ihn tatsächlich verschoben habe, daher werde ich einige vorstellen. Immerhin wird es viel schöner angezeigt als Tk. Ich bin auch froh, dass das Gtk-Thema angewendet wurde.
Bei Anzeige in Gtk mit tk_wrapper
Das Widget wird so generiert.
Wenn Sie den Schieberegler bewegen oder den Schalter ein- und ausschalten, wird der Inhalt der Funktion ausgeführt. (Zeigen Sie jetzt nur den Inhalt der Variablen an.) Durch Drücken der Taste können Sie zu diesem Zeitpunkt eine andere Funktion ausführen und sich auf den Wert der Variablen zu diesem Zeitpunkt beziehen.
Stellen Sie schließlich den gesamten Code bereit. Es tut mir leid, dass es noch wenige Kommentare gibt, aber ich hoffe, es hilft.
gtk_wrapper.py
#! /usr/bin/env python
# -*- coding:utf-8 -*-
#
# written by ssh0, October 2014.
from __future__ import print_function
__doc__ = '''IPython-like Gtk wrapper class.
You can create Scalebar, Switch, ComboBox via simple interface.
usage example:
>>> from gtk_wrapper import interactive
>>> def f(a,b=20):
... return a + b
...
>>> w = interactive(f, a=(0, 20), b=20)
(you can add buttons and label here manually)
(then, you should add the next line)
>>> w.display()
(and you can get the result for f(a,b) by)
>>> w.result
32
(or get the arguments with a dictionary)
>>> w.kwargs
{'a':8, 'b':24}
'''
from gi.repository import Gtk
import inspect
class interactive(Gtk.Window):
def __init__(self, func, title='title', **kwargs):
self.__doc__ = __doc__
self.func = func
self.kwargs = dict()
args, varargs, keywords, defaults = inspect.getargspec(self.func)
d = []
for default in defaults:
d.append(default)
self.kwdefaults = dict(zip(args[len(args) - len(defaults):], d))
Gtk.Window.__init__(self, title=title)
hbox = Gtk.Box(spacing=6)
self.add(hbox)
self.listbox = Gtk.ListBox()
self.listbox.set_selection_mode(Gtk.SelectionMode.NONE)
hbox.pack_start(self.listbox, True, True, 0)
self.status = Gtk.Label()
for kw, arg in kwargs.items():
kw = str(kw)
arg_type = type(arg)
if arg_type == tuple:
# type check for elements in tuple
argtype = self.type_check(arg)
if argtype == str:
self.combobox_str(kw, arg)
else:
self.scale_bar(kw, arg, argtype)
elif arg_type == int or arg_type == float:
self.scale_bar(kw, [arg], arg_type)
elif arg_type == bool:
self.switch(kw, arg)
elif arg_type == str:
self.label(arg)
self.kwargs[kw] = arg
elif arg_type == dict:
self.combobox_dict(kw, arg)
else:
raise TypeError
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
row.add(hbox)
hbox.pack_start(self.status, True, True, 10)
self.status.set_text(str(self.kwargs))
self.listbox.add(row)
def display(self):
self.connect("delete-event", Gtk.main_quit)
self.show_all()
Gtk.main()
def status_change(self):
self.status.set_text(str(self.kwargs))
self.kwargs_for_function = self.kwdefaults
for k, v in self.kwargs.items():
self.kwargs_for_function[k] = v
self.result = self.func(**self.kwargs_for_function)
def set_value(self, kw, new_value):
# if argument is already given in func, use it for a default one
if kw in self.kwdefaults:
self.kwargs[kw] = self.kwdefaults[kw]
return self.kwdefaults[kw]
else:
self.kwargs[kw] = new_value
return new_value
def type_check(self, arg):
argtype = type(arg[0])
if not all([type(a) == argtype for a in arg]):
raise TypeError("""types in a tuple must be the same.
int or float: Scalebar
str : Combobox""")
return argtype
def add_label(self, kw, parent):
label = Gtk.Label(kw, xalign=0)
parent.pack_start(label, True, True, 10)
def scale_bar(self, kw, arg, argtype):
def scale_interact(scale, _type):
if _type == int:
self.kwargs[kw] = int(scale.get_value())
else:
self.kwargs[kw] = float(scale.get_value())
self.status_change()
# length check for tuple
len_arg = len(arg)
if len_arg > 3 or len_arg == 0:
raise IndexError("tuple must be 1 or 2 or 3 element(s)")
if argtype == int:
scale_digit = 0
elif argtype == float:
scale_digit = 2
else:
raise TypeError("arg must be int or float")
# set the values
if len_arg == 3:
scale_from = arg[0]
scale_to = arg[1]
scale_digit = arg[2]
elif len_arg == 2:
scale_from = arg[0]
scale_to = arg[1]
else:
scale_from = arg[0] * (-1)
scale_to = arg[0] * 3
# create scale widget in listbox
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
row.add(hbox)
self.add_label(kw, hbox)
scale = Gtk.Scale()
scale.set_range(scale_from, scale_to)
scale.set_digits(scale_digit)
scale.set_value(self.set_value(kw, arg[0]))
scale.set_draw_value(True)
scale.connect('value-changed', scale_interact, argtype)
hbox.pack_start(scale, True, True, 10)
self.listbox.add(row)
def switch(self, kw, arg):
def on_switch_activated(switch, gparam):
self.kwargs[kw] = switch.get_active()
self.status_change()
# create switch widget in listbox
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
row.add(hbox)
self.add_label(kw, hbox)
switch = Gtk.Switch()
switch.connect("notify::active", on_switch_activated)
switch.set_active(self.set_value(kw, arg))
hbox.pack_start(switch, False, False, 10)
self.listbox.add(row)
def combobox_str(self, kw, arg):
def on_combo_changed(combo):
tree_iter = combo.get_active()
if tree_iter is not None:
self.kwargs[kw] = arg[tree_iter]
self.status_change()
argstore = Gtk.ListStore(str)
for a in arg:
argstore.append([a])
# create combobox widget in listbox
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
row.add(hbox)
self.add_label(kw, hbox)
combo = Gtk.ComboBox.new_with_model(argstore)
combo.connect("changed", on_combo_changed)
renderer_text = Gtk.CellRendererText()
combo.pack_start(renderer_text, True)
combo.add_attribute(renderer_text, "text", 0)
combo.set_active(arg.index(self.set_value(kw, arg)))
hbox.pack_start(combo, False, False, True)
self.listbox.add(row)
def combobox_dict(self, kw, arg):
def on_combo_changed(combo):
tree_iter = combo.get_active()
if tree_iter is not None:
self.kwargs[kw] = values[tree_iter]
self.status_change()
argstore = Gtk.ListStore(str)
keys = list(arg.keys())
values = list(arg.values())
for a in keys:
argstore.append([a])
# create combobox widget in listbox
row = Gtk.ListBoxRow()
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
row.add(hbox)
self.add_label(kw, hbox)
combo = Gtk.ComboBox.new_with_model(argstore)
combo.connect("changed", on_combo_changed)
renderer_text = Gtk.CellRendererText()
combo.pack_start(renderer_text, True)
combo.add_attribute(renderer_text, "text", 0)
combo.set_active(values.index(self.set_value(kw, arg)))
hbox.pack_start(combo, False, False, True)
self.listbox.add(row)
if __name__ == '__main__':
from gi.repository import Gtk
def f(x=12, y=20, z='III', o=False, i=20):
print("x: {0}, y: {1}, z: {2}, o: {3}, i: {4}".format(x, y, z, o, i))
def b1(button):
print(w.kwargs)
buttons = [('b1', b1), ('exit', Gtk.main_quit)]
w = interactive(f, x=10, y=(1., 100.),
z=("ZZZ", "III", "foo", "bar"),
i={'0': 0, '10': 10, '20': 20},
o=True
)
row = Gtk.ListBoxRow()
hbox = Gtk.HBox(spacing=10)
row.add(hbox)
for b in buttons:
button = Gtk.Button(b[0])
button.connect('clicked', b[1])
hbox.pack_start(button, True, True, 0)
w.listbox.add(row)
w.display()
Ich wollte hauptsächlich Gtk verwenden, daher ist dies ein Absatz. Die Funktion wird jedoch immer noch so oft ausgeführt wie die Anzahl der Schieberegler (das heißt, dies ist nicht nur für Tk ein Problem), und die Anzeigereihenfolge ist ebenfalls nicht in Ordnung. Die Punkte, die in Zukunft verbessert werden sollen, sind die oben genannten Punkte und die Verbesserung der Menüleiste. Ich denke, Sie können Dateien leicht lesen. Qt ist in der Warteschleife, weil ich nicht viel Gelegenheit habe, es persönlich zu verwenden (Ubuntu ...).
Recommended Posts