Problem with changing the value of main button in KivyMD Menu - oop

I have created a KivyMD Menu. When I click on the main Button, the menu is opening without a problem. However when I click on a menu button the value of the main button is not changing. Nothing happens. I thought the code is sufficient to achieve it. Does anyone know a solution? Thank you in advance!
py file:
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.menu import MDDropdownMenu
Window.size = (400, 800)
class homescreen(Screen):
pass
GUI = Builder.load_file("main.kv")
class MainApp(MDApp, homescreen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.homescreen = Builder.load_string("homescreen")
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
self.menu = MDDropdownMenu(
caller=self.ids.drop_item,
items=menu_items,
#position="center",
width_mult=4,
)
self.menu.bind(on_release=self.set_item)
def set_item(self, instance_menu, instance_menu_item):
self.ids.drop_item.set_item(instance_menu_item.text)
self.menu.dismiss()
def build(self):
return self.homescreen
if __name__ == "__main__":
MainApp().run()
main.kv:
<homescreen>:
MDDropDownItem:
id: drop_item
pos_hint: {'center_x': .5, 'center_y': .5}
text: "Select"
on_release: app.menu.open()

Here is your improved code
py file:
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.menu import MDDropdownMenu
Window.size = (400, 800)
class homescreen(Screen):
pass
GUI = Builder.load_file("main.kv")
class MainApp(homescreen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.homescreen = Builder.load_string("homescreen")
menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
self.menu = MDDropdownMenu(
caller=self.ids.drop_item,
items=menu_items,
callback=self.set_item,
width_mult=4,
)
def set_item(self, instance_menu_item):
self.ids.drop_item.text = instance_menu_item.text
self.menu.dismiss()
def build(self):
return self.homescreen
class app(MDApp):
def build(self):
return MainApp()
if __name__ == "__main__":
app().run()
main.ky
<homescreen>:
MDDropDownItem:
id: drop_item
pos_hint: {'center_x': .5, 'center_y': .5}
text: "Select"
on_release: root.menu.open()

Related

PyQt, How to switch transparent-setting for subwindow

I want switch WindowTransparentForInput statement of sub-window.
At following code, I wrote, subwindow will close instead switch the statement.
Could you please to point the problem?
import sys
from PyQt5 import QtWidgets as qtw, QtGui as qtg, QtCore as qtc
class Main(qtw.QWidget):
def __init__(self):
super().__init__()
self.mainWindow = qtw.QWidget(self)
self.mainWindow.setGeometry(100,100,200,200)
label = qtw.QLabel('Main window', self)
self.switch = qtw.QCheckBox('Transparent for input on sub window', self)
self.switch.setChecked(False)
self.switch.stateChanged.connect(self.switchAction)
mainLayout = qtw.QVBoxLayout()
self.setLayout(mainLayout)
mainLayout.addWidget(label)
mainLayout.addWidget(self.switch)
self.subwindow = qtw.QWidget()
self.subwindow.setGeometry(150,100,200,200)
sublabel = qtw.QLabel('Sub window', self.subwindow)
self.show()
self.subwindow.show()
def switchAction(self):
if self.switch.isChecked:
self.subwindow.setWindowFlags(qtc.Qt.WindowTransparentForInput | qtc.Qt.FramelessWindowHint)
else:
self.subwindow.setWindowFlags(qtc.Qt.FramelessWindowHint)
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = Main()
sys.exit(app.exec())
It was solved by modifying switchAction() as follow.
I'm sorry for your notation.
def switchAction(self):
if self.switch.isChecked():
self.subwindow.close()
self.subwindow.setWindowFlags(self.subwindow.windowFlags() | qtc.Qt.WindowTransparentForInput)
self.subwindow.show()
else:
self.subwindow.close()
self.subwindow.setWindowFlags(self.subwindow.windowFlags() & ~qtc.Qt.WindowTransparentForInput)
self.subwindow.show()

how to transmit true value to formal parameter in decorator function(pyqtSlot())?

first, see code below:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
#pyqtSlot(int)
def on_sld_valueChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
self.lcd = QLCDNumber(self)
self.sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
self.sld.valueChanged.connect(self.on_sld_valueChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
I'm a little puzzled about how the true value in sld is transmitted to the formal parameter 'value' in the slot function : def sld_valChanged(self, value).
Because i can't see something like this: self.sld.valueChanged.connect(partial(self.sld_valChanged, self.sld.value))
Could someone explain that?

KIVY python: Slider inside ScrollView

I created a scroll view in which i put some labels and 2 sliders.
The scroll works perfectly, but I can't change the slider's value with my mouse...
Please run this code and see:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.slider import Slider
from kivy.uix.textinput import TextInput
class Home(BoxLayout):
def __init__(self, **kwargs):
super(Home, self).__init__(**kwargs)
self.layout = GridLayout(cols=1, padding=5, spacing=20, size_hint=(1, None))
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(50):
if i%25==0:
btn = Slider(min=1, max=10, value=4)
else:
btn = Label(text=str(i), color=(0,0,0,1), size=(32, 32), size_hint=(1, None))
self.layout.add_widget(btn)
self.scrll = ScrollView(size_hint=(1, .6), pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False)
self.scrll.add_widget(self.layout)
self.add_widget(self.scrll)
class MyAppli(App):
def build(self):
Window.clearcolor = (1,1,1,1)
return Home()
if __name__ == '__main__':
MyAppli().run()
Okay when you work with slider you shall redefine the on_touch_down, on_touch_up and on_touch_move method to handle those events:
-main.py :
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.properties import NumericProperty
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.slider import Slider
class Home(BoxLayout):
def __init__(self, **kwargs):
super(Home, self).__init__(**kwargs)
self.b = []
self.layout = GridLayout(cols=1, padding=5, spacing=20, size_hint=(1, None))
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(50):
if i % 25 == 0:
self.b.append(MySlider(min=1, max=10, value=4, height=32, size_hint=(1, None)))
else:
self.b.append(Label(text=str(i), color=(0,0,0,1), height=32, size_hint=(1, None)))
self.layout.add_widget(self.b[i])
self.scrll = ScrollView(size_hint=(1, .6), pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False)
self.scrll.add_widget(self.layout)
self.add_widget(self.scrll)
def update(self, *args):
for i in range(50):
if i % 25 == 0:
self.b[i].begin = self.b[i].pos[0]
self.b[i].len = self.b[i].size[0]
class MySlider(Slider):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
super(MySlider, self).on_touch_down(touch)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
super(MySlider, self).on_touch_up(touch)
def on_touch_move(self, touch):
if self.collide_point(*touch.pos):
super(MySlider, self).on_touch_move(touch)
class MyAppli(App):
def build(self):
Window.clearcolor = (1,1,1,1)
return Home()
if __name__ == '__main__':
MyAppli().run()
-some outputs :
I hope this helps !

pyqt5 videowidget not showing in layout

I am writing a program with pyqt5 where pressing a button first cycles through some pictures then cycles through some videos.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
import argparse
import sys
class MainWindow(QMainWindow):
def __init__(self,args):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = CentralWidget(args)
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
QCoreApplication.instance().quit()
self.centralwidget.startvid()
class CentralWidget(QWidget):
def __init__(self,args):
super(CentralWidget, self).__init__()
self.layout = QVBoxLayout()
self.layout.setAlignment(Qt.AlignCenter)
self.setLayout(self.layout)
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.vw = QVideoWidget()
self.player.setVideoOutput(self.vw)
def startvid(self):
self.layout.addWidget(self.vw)
url= QUrl.fromLocalFile(glob.glob("videos/*")[0])
content= QMediaContent(url)
self.player.setMedia(content)
self.player.setVideoOutput(self.vw)
self.player.play()
if __name__== "__main__":
parser = argparse.ArgumentParser()
#~ parser.add_argument("-nb","--nobox",action="store_true", help="do not wait for the box connection")
args = parser.parse_args()
app = QApplication(sys.argv)
mainwindow = MainWindow(args)
#~ mainwindow.showFullScreen()
mainwindow.show()
sys.exit(app.exec_())
I tried to paste the minimal code. The thing is, I press the button nothing shows, although I used examples like this one PyQt5 - Can't play video using QVideoWidget to test if playing the video is ok, and these work. It's as if it is not adding the widget to the layout or something. Any idea what might be wrong?
I had to use QGraphicsView to achieve what I wanted, here is a fix:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = VideoPlayer()
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
self.centralwidget.phaseQuit(2)
self.centralwidget.play()
class VideoPlayer(QWidget):
def __init__(self, parent=None):
super(VideoPlayer, self).__init__(parent)
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.videoItem = QGraphicsVideoItem()
self.videoItem.setSize(QSizeF(640, 480))
scene = QGraphicsScene(self)
graphicsView = QGraphicsView(scene)
scene.addItem(self.videoItem)
layout = QVBoxLayout()
layout.addWidget(graphicsView)
self.setLayout(layout)
self.mediaPlayer.setVideoOutput(self.videoItem)
self.counter = 0
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
pass
else:
self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(glob.glob("videos/*")[self.counter])))
self.mediaPlayer.play()
self.counter += 1
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
player = MainWindow()
player.show()
sys.exit(app.exec_())

Why does ConfigParserProperty only work for Widgets created with kv in examples below

The following code works as I expect. When I enter a Number in TextInput and press RETURN, the number is shown in all 3 Labels.
#!/usr/bin/python
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ConfigParserProperty
Builder.load_string("""
<MyBoxLayout>
TextInput:
text: "insert Number <RETURN>"
multiline: False
on_text_validate: root.numberprop=self.text
Label:
text: str(root.numberprop)
Label:
text: str(root.numberprop)
Label:
text: str(root.numberprop)
""")
class MyBoxLayout(BoxLayout):
numberprop= ConfigParserProperty(3, 'one', 'two', 'app',
val_type=int, errorvalue=41)
class TstApp(App):
def build_config(self, config):
config.setdefaults('one', {'two' : '70'})
def build(self, **kw):
return MyBoxLayout()
if __name__ == '__main__':
TstApp().run()
The following code does not work as I expect. When I enter a number in Textinput and press RETURN, only the last Label shows the number.
#!/usr/bin/python
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.properties import ConfigParserProperty
def MyConfigParserProperty():
return ConfigParserProperty(3, 'one', 'two', 'app',
val_type=int, errorvalue=41)
Builder.load_string("""
<MyBoxLayout>
TextInput:
text: "insert Number <RETURN>"
multiline: False
on_text_validate: root.numberprop=self.text
<MyLabel>
text: str(root.numberprop)
""")
class MyLabel(Label):
numberprop=MyConfigParserProperty()
class MyBoxLayout(BoxLayout):
numberprop=MyConfigParserProperty()
def __init__(self, **kw):
super(MyBoxLayout, self).__init__(**kw)
for i in range(3):
self.add_widget(MyLabel())
class TstApp(App):
def build_config(self, config):
config.setdefaults('one', {'two' : '70'})
def build(self, **kw):
return MyBoxLayout()
if __name__ == '__main__':
TstApp().run()
I need a way to create Labels dynamically. How can I do it ?
The following code solves the problem.
#!/usr/bin/python
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.properties import ConfigParserProperty
Builder.load_string("""
<MyBoxLayout>
TextInput:
text: "insert Number <RETURN>"
multiline: False
on_text_validate: app.numberprop=self.text
<MyLabel>
text: str(app.numberprop)
""")
class MyLabel(Label):
pass
class MyBoxLayout(BoxLayout):
def __init__(self, **kw):
super(MyBoxLayout, self).__init__(**kw)
for i in range(3):
self.add_widget(MyLabel())
class TstApp(App):
numberprop=ConfigParserProperty(3, 'one', 'two', 'app',
val_type=int, errorvalue=41)
def build_config(self, config):
config.setdefaults('one', {'two' : '70'})
def build(self, **kw):
return MyBoxLayout()
if __name__ == '__main__':
TstApp().run()