from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.submit = Button(text='Order', font_size=40)
self.add_widget(self.submit)
self.submit.bind(on_press=self.pressed)
def pressed(self, instance):
pressing = Secondtab()
pressing()
class Secondtab(GridLayout):
def __init__(self, **kwargs):
super(Secondtab, self).__init__(**kwargs)
self.cols = 5
self.submit = Button(text='Drinks', font_size=40)
self.add_widget(self.submit)
print('check')
def __call__(self):
print('new tab')
class MyApp(App):
def build(self):
return LoginScreen()
if __name__ == '__main__':
MyApp().run()
So I want the window to change to a new layout when I press the first button. I tought making a new grid class and calling it would work but it didnt work as I expected. I dont want the button to open a new window tho I want the current window to refresh to the new layout.
As #John Anderson suggested. Take a look at the screen manager widget. The 'current window' must be a populated screen widget and you could change the current screen by assigning the next screen's name to the current attribute.
This will help you I guess. Using ScreenManager:
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.submit = Button(text='Order', font_size=40)
self.add_widget(self.submit)
self.submit.bind(on_press=self.pressed)
def pressed(self, instance):
pressing = Secondtab()
pressing()
myapp.screen_manager.transition = SlideTransition(direction='left', duration=.25) #You can change transition speed or you could just remove it to set it on default
myapp.screen_manager.current = 'Secondtab'
class MyApp(App):
def build(self):
return LoginScreen()
self.screen_manager = ScreenManager()
self.loginscreen = LoginScreen()
screen = Screen(name='LoginScreen')
screen.add_widget(self.loginscreen)
self.screen_manager.add_widget(screen)
self.secondtab = Secondtab()
screen = Screen(name='Secondtab')
screen.add_widget(self.secondtab)
self.screen_manager.add_widget(screen)
return self.screen_manager
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 button that runs a loop and updates the window accordingly. I want another "pause" button that pauses this loop but it doesn't seem like I can do that while the loop is running. Perhaps threading is the solution (I tried GLib.timeout_add_seconds without success) - what is the easiest way to make this work?
I have attached my faulty code:
import sys
from time import sleep
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class LoopButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
self.message = "1"
button = Gtk.Button.new_with_label("Run")
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
msg = int(self.message)
while self.GUI.is_paused == False:
self.GUI.restart_window(str(msg))
msg += 1
while Gtk.events_pending():
Gtk.main_iteration()
sleep(1)
self.GUI.is_paused = True
class PauseButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
button = Gtk.Button.new_with_label("Pause")
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
self.GUI.is_paused = True
class GUI:
def __init__(self):
self.is_paused = False
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Default label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.box.pack_start(LoopButton(self), True, True, 0)
self.box.pack_start(PauseButton(self), True, True, 0)
self.window_grid.add(self.box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Default label"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
Depending on what you really do in the loop there may be more necessary details, but below is an example of how looping is normally avoided in GLib/Gtk. The caveats of this method are: A) one iteration must be fast enough to not affect UI updates (a few milliseconds at most). B) The timing is not exact: the timeout function might not be called exactly 2 seconds after the previous call.
import gi
from gi.repository import GLib
class GUI:
def __init__(self):
# initialize the UI here...
# setup updates every two seconds
GLib.timeout_add_seconds(2, self.timeout_update)
def timeout_update(self):
# update your widgets here
print ("Updating UI now...")
# yes, we want to be called again
return True
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 came across this rather unexpected problem. I have a gtk.TreeView with a single text column, that is rendered by gtk.CellRendererText. What I want is that the user can mark the displayed text using the mouse and get it into the clipboard by pressing ctrl+c. (I am referring to the very basic feature present in every webbrowser and texteditor). However, gtk won't let me do it. I have a simple example here, with non-markable / non-highlightable text:
import gtk
class TreeViewExample(gtk.TreeView):
def __init__(self):
gtk.TreeView.__init__(self)
self.get_selection().set_mode(gtk.SELECTION_NONE)
self.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_HORIZONTAL)
# create model
self.list_store = gtk.ListStore(str)
self.list_store.append(['Hello, this is some \n multiline text.'])
self.list_store.append(['Another text.'])
self.set_model(self.list_store)
# create text column
col = gtk.TreeViewColumn('Text Column')
self.append_column(col)
cell = gtk.CellRendererText()
col.pack_start(cell, True)
col.add_attribute(cell, 'text', 0)
class MasterWindow(object):
def destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
self.window.connect("destroy", self.destroy)
self.window.add(TreeViewExample())
self.window.show_all()
if __name__ == '__main__':
mw = MasterWindow()
gtk.main()
I could of course make the cell editable, because the editable mode provides the feature. But that is far from elegant, because it is some kind of popup, that breaks the line wrap and, well, edits the text. What i need is a cell, that is not selectable, editable or anything, but has text, that can be copied.
Does anyone have a solution? Thanks!
I made some changes in the code.
Try the code below, this example works well and I am sure that is the answer to your question.
Hope this helps you in the future of their knowledge and coding.
import gtk
class TreeViewExample():
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
model = gtk.ListStore(str)
model.append(['a'])
model.append(['b'])
model.append(['c'])
treeview = gtk.TreeView(model)
self.renderer = gtk.CellRendererText()
self.renderer.set_property('editable', True)
treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=0)
self.window.add(treeview)
self.window.show_all()
if __name__ == '__main__':
TreeViewExample()
gtk.main()
I made some changes in the code. Trying to answer questions of #Flimm.I hpe Helps you #Flimm.
import gtk
class TreeViewExample():
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
self.model = gtk.ListStore(str,str)
self.model.append(['a','b'])
self.model.append(['c','a'])
self.model.append(['d','a'])
self.model.append(['e','a'])
self.treeview = gtk.TreeView(self.model)
self.renderer = gtk.CellRendererText()
self.renderer.set_property('editable', True)
self.renderer.connect('edited', self._text_changed, 0)
self.treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=0)
self.treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=1)
self.window.add(self.treeview)
self.window.show_all()
def _text_changed( self, w, row, new_value, column):
self.model[row][column] = new_value
if __name__ == '__main__':
TreeViewExample()
gtk.main()
If I run this example code
class ExampleGUIElement extends Panel
{
preferredSize = new Dimension(100, 100)
val rand : Random = Random
override def paintComponent(g: Graphics2D) = g.drawLine(rand.nextInt(10),rand.nextInt(10),rand.nextInt(90) + 10 ,rand.nextInt(90) + 10)
}
object GUITest extends SimpleSwingApplication
{
def top = new MainFrame
{
contents = new ExampleGUIElement
}
}
It obviously only shows the one line that has been draw initially. If I want a periodic repaint I normally would just make a Timer that calls repaint on the most outer JFrame.
But SimpleSwingApplication does not have this method, at least I can not find it, and calling top.repaint instead just does nothing. So how do you periodically repaint the whole thing?
Consider calling peer on the top (see MainFrame), and then calling repaint on that:
top.peer.repaint()
Also, don't forget to call top.pack().
I realize this is dated, but I extracted your Panel into a val and added a timer to repaint it:
def top = new MainFrame
{
val example = new ExampleGUIElement
contents = example
val timer=new javax.swing.Timer(250, Swing.ActionListener(e =>
{
example.repaint()
}))
timer.start()
}