I've been trying to build a simple GUI using Kivy on a Raspberry Pi running Raspian Jessie. But I'm having some issues...
My TextInput isn't accepting any keyboard input, but it is focusing when I click inside the text input box (with a blinking cursor and all). This isn't an issue with my keyboard, because I can successfully interrupt the program with Ctrl-C.
I suspect there might be an issue with TextInput being placed inside a BoxLayout, but if I didn't do that, the TextInput would take up the entire screen. If the BoxLayout is the issue, then how could I limit the size of the TextInput (since apparently size_hints don't do anything). Any help would be appreciated!
Here's my code. For simplicity, I've decided to separate out my code into .py and .kv files:
gui.kv
#:kivy 1.4
#:import turn_on led_controller.turn_on
#:import turn_off led_controller.turn_off
#:set Iset 100
FloatLayout:
ToggleButton:
id: on_off_switch
text: "ON" if self.state == 'down' else "OFF"
pos_hint: {'center_x': 0.2, 'center_y': 0.2}
size_hint: 0.3, 0.2
on_state: turn_on(app.ser, Iset) if self.state == 'down' else turn_off(app.ser)
Button:
text: "TODO: Graph"
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint: 0.7, 0.3
BoxLayout:
pos_hint: {'center_x': 0.6, 'center_y': 0.9}
size_hint: 0.7, 0.1
TextInput:
id: textbox
gui.py
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.textinput import TextInput
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
class GUI(App):
from led_controller import init_serial
ser = init_serial()
def build(self):
return Builder.load_file('gui.kv')
if __name__ == '__main__':
GUI().run()
Related
I have a form created with PyQt5 Designer. Within this form, I have a QPushButton and a QWidget. I want to draw shapes on the QWidget with QPainter. I want to draw on the QWidget (named drawing_area) with custom methods such as my_rectangle(), my_line(), etc. I also want to trigger a custom function clear_drawings() to clean the drawings on the widgets by a button click. Following is my UI. I couldn't figure out how to target a certain QWidget within a form. I appreciate guidance here.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(770, 347)
self.drawButton = QtWidgets.QPushButton(Form)
self.drawButton.setGeometry(QtCore.QRect(20, 60, 91, 24))
self.drawButton.setObjectName("drawButton")
self.drawing_area = QtWidgets.QWidget(Form)
self.drawing_area.setGeometry(QtCore.QRect(280, 30, 381, 191))
self.drawing_area.setAutoFillBackground(False)
self.drawing_area.setObjectName("drawing_area")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.drawButton.setText(_translate("Form", "Click to Draw!"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
I have a rather large App split in a single .kv file and a GUI.py file accessing a library of other .py files. I came to a point where i want to organize everything and split up large layouts into different classes and .kv files.
Currently im working on a function which should add and remove a certain layout to my main layout while still accessing variables and functions of the base class (called BoxL). I tried various things, but i dont know how i can hand over/instantiate my main class to/in my new class.
Im trying to build a rough minimal example:
Main python file: GUI.py
import kivy
from kivy.app import App
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
class AdvancedClass(BoxLayout):
"""This is my new class from which i want to access BoxL class."""
pass
class BoxL(BoxLayout):
def __init__(self):
super(BoxL, self).__init__()
some_variable = 1
advanced_mode_enabled = False
def some_function(self):
print(self.some_variable)
print('Im also doing stuff in GUI.kv file with ids')
self.ids.test_label.text = '[b]some text with markup'
def advanced_mode(self):
if not self.advanced_mode_enabled:
print('Enabling advanced mode ..')
self.ids.master_box.add_widget(self.advanced_class_obj)
self.advanced_mode_enabled = True
else:
print('Disabling advanced mode ..')
self.ids.master_box.remove_widget(self.advanced_class_obj)
self.advanced_mode_enabled = False
class GUI(App):
def build(self):
Builder.load_file('layouts.kv') # i read its best to instanciate kivy files here once everything is loaded
BoxL.advanced_class_obj = AdvancedClass()
if __name__ == "__main__":
GUI().run()
Main layout file: GUI.kv
<BoxL>:
orientation: 'vertical'
id: master_box
Label:
text: str(root.some_variable)
Button:
text: 'Change variable'
on_release:
root.some_variable = 2
Button:
text: 'Add advanced layout'
on_release:
root.advanced_mode(self)
New layout file layouts.kv from which i want to access functions/variables of BoxL class in GUI.py:
<AdvancedClass>:
orientation: 'vertical'
Label:
text: '[b]TEST'
TextInput:
hint_text: 'TEST'
Button:
text: 'KLICK'
on_release:
# print(parent.some_variable)
# print(self.some_variable)
# print(BoxL.some_variable)
print('Im not sure how to do this .. ') # issue-point
I hope this covers everything. Im struggling with this for quite a while.
Figured it out: app.root.FUNCTION()
I can't get double clicking to work on a Surface Pro 3 (Fedora; Kernel 4.28; Gnome 3.18, Gtk3). Two fast consecutive taps are not converted to a 2button event in Gtk+. See the small Python program below, which works fine for a normal mouse or touch pad.
I've checked that it is not a problem with the tap time and not the tap distance as you can see in the program. Where could this problem originate from? GDK_TOUCH_MASK?
To clarify, button events are received, but never converted to 2button event
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Double Click Test")
self.button = Gtk.Button.new_with_label("Double-click test\n\n")
self.button.connect("button-press-event", self.test_button_clicked)
self.button.connect("button-release-event", self.test_button_released)
settings = Gtk.Settings.get_default()
Gtk.Settings.set_property(settings,'gtk-double-click-distance',1000)
print Gtk.Settings.get_property(settings,'gtk-double-click-distance')
Gtk.Settings.set_property(settings,'gtk-double-click-time',1000)
print Gtk.Settings.get_property(settings,'gtk-double-click-time')
self.add(self.button)
def test_button_clicked(self, widget, event):
if event.type == Gdk.EventType._2BUTTON_PRESS:
widget.set_label(("Success!"))
GLib.timeout_add(1000, self.reset_test_button, widget)
return True
def test_button_released(self, widget, event):
return True
def reset_test_button(self, widget):
widget.set_label(("Double-click test"))
return False
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
I have the following peace of code
from ipywidgets import widgets
from IPython.display import display
import numpy as np
class Test(object):
def __init__(self, arraylen):
self.a = np.random.randn(arraylen)
self.button = widgets.Button(description = 'Show')
self.button.on_click(self.show)
display(self.button)
self.button1 = widgets.Button(description = 'Show1')
self.button1.on_click(self.show)
display(self.button1)
def show(self, ev = None):
np.savetxt('test',self.a)
self.button.disabled = True
test = Test(10)
The output is two buttons in a column as shown here:
Would it also be possible, to embed the buttons in a HTML table (where I could choose them to be in a row), or any other organization scheme? Maybe it could look like this:
You could use (a very basic example):
from IPython.display import display
from ipywidgets import widgets
button1 = widgets.Button(description = 'Button1')
button2 = widgets.Button(description = 'Button2')
display(widgets.HBox((button1, button2)))
Here you can find basic and more complete examples about the use of the widgets. If you are using Jupyter you should adapt some info (from ipywidgets import widgets instead from IPython.html import widgets,...).
I find myself waiting for the GUI of my Traits/UI application to update, with each backspace and/or digit entry in a particular field. How can I get the Traits/UI notification system to wait until I press RETURN before it sends out change notifications?
You want to use the auto_set and enter_set attributes of a TextEditor. auto_set=False stops updating the trait on every keystroke, and enter_set=True causes it to update on Enter. See here for docs.
For example:
from traits.api import HasTraits, Str
from traitsui.api import View, TextEditor, Group, Item
class Foo(HasTraits):
my_str = Str()
traits_view = View(
Item('my_str',
style='custom',
editor=TextEditor(
auto_set=False,
enter_set=True,
),
),
Item('my_str',
style='readonly'
),
)
if __name__ == '__main__':
f = Foo()
f.configure_traits()