.py ve .glade arasında bağlantı kurma

Başlatan mhmtkrktr, 29 Ekim 2017 - 22:32:58

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

mhmtkrktr

Merak edip biraz python ile uğraşayım dedim. Tkinter ile birşeyler yapmaya çalıştım ama bir svg dosyasını 5 saatte pencereye alamayınca onu bırakıp pygtk ya geçiş yaptım. Sabahtan bu yana biraz yol kat ettim ama takılıp çözümünü bulamadığım yerlerde yardıma ihtiyacım var.

https://i.hizliresim.com/nJON61.png

Resimde görünen ses kontrol işlevini hazırlamaya çalışıyorum. Kontrol fonksiyonlarını tamamladım. Script olarak çalışıyor.

Arayüzü şimdilik kabaca tamam.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window">
    <property name="name">main</property>
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="is_focus">True</property>
    <property name="events">GDK_KEY_PRESS_MASK | GDK_STRUCTURE_MASK</property>
    <property name="opacity">0.28000000000000003</property>
    <property name="margin_top">4</property>
    <property name="border_width">4</property>
    <property name="resizable">False</property>
    <property name="window_position">center-always</property>
    <property name="default_width">150</property>
    <property name="default_height">140</property>
    <property name="skip_taskbar_hint">True</property>
    <property name="focus_on_map">False</property>
    <property name="decorated">False</property>
    <property name="deletable">False</property>
    <property name="gravity">static</property>
    <signal name="delete-event" handler="on_main_show" object="progress" swapped="no"/>
    <child>
      <object class="GtkBox" id="popup">
        <property name="name">pop_up</property>
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">2</property>
        <property name="margin_right">2</property>
        <property name="margin_top">2</property>
        <property name="margin_bottom">2</property>
        <property name="orientation">vertical</property>
        <property name="spacing">21</property>
        <property name="baseline_position">bottom</property>
        <child>
          <object class="GtkImage">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="margin_top">10</property>
            <property name="pixel_size">96</property>
            <property name="icon_name">audio-volume-high-symbolic</property>
            <property name="icon_size">1</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkLevelBar" id="progress">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="margin_left">9</property>
            <property name="margin_right">9</property>
            <property name="margin_bottom">10</property>
            <signal name="show" handler="on_progress_show" swapped="no"/>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <child type="titlebar">
      <placeholder/>
    </child>
  </object>
</interface>


Pygtk ile arayüzü de birleştirebildim.

#!/usr/bin/python3


import gi, time
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class Handler:
    def on_progress_show(self, *args):
        self.set_border_width(10)
        self.progressbar = Gtk.ProgressBar()
        self.timeout_id = GObject.timeout_add(50, self.on_timeout, None)
        self.activity_mode = False
    def on_timeout(self, user_data):
        if self.activity_mode:
            self.progressbar.pulse()
        else:
            new_value = self.progressbar.get_fraction() + 0.1

            if new_value > 1:
                new_value = 0

            self.progressbar.set_fraction(new_value)
        return True


builder = Gtk.Builder()
builder.add_from_file("volume.ui")
builder.connect_signals(Handler())

window = builder.get_object("window")
window = builder.get_object("progress")
window.show_all()

Gtk.main()


Çözüm bulamadığım noktalar;

1 : Sistemin mevcut ses seviyesini şu şekilde alabiliyorum.
card = Popen(['amixer', 'sset', 'Master', val], stdout = PIPE)
out = card .communicate()[0]
vol = str(out) .split('[')[1] .split(']')[0]
pb["maximum"] = 150
pb["value"] = vol[:-1]

Fakat aldığım bu değeri pygtk içinden nasıl .ui üzerine yansıtabileceğimi anlamadım. Tikinter ilkel olmasa onda çok basit şekilde yapmıştım ama bu taraf biraz karışık geldi. İşin kötüsü fazla bir kaynak yok. Bulabildiğim en iyisi şu oldu. http://python-gtk-3-tutorial.readthedocs.io/en/latest/builder.html
Burada da sadece <button> <signal> ile örneklendirilmiş.

2: Uygulama kısayol üzerinden çalışıyor. Tk ile window .after(1000, lambda: window .destroy() )  şeklinde, süreli olarak uygulamayı sonlandırabiliyordum. Fakat bu komut bu tarafta işe yaramadı.
Yapmak istediğim, eğer herhangi bir tuşa (up/down) 1 sn boyunca basılmazsa pencere kapansın. Fakat 1 sn içerisinde tekrar tuşa basılırsa mevcut pencerede progress bar (yeni seviyeye göre) değişsin.
Bu durumda aslında yukarıda ki ile bağlantılı. Sorun, fonksiyonları nasıl içeri alabileceğimi anlayamadım. 

Bunu hazırlamakta ki amacım, hem python ile biraz uğraşmak istemem, hem de yazılımsal hacim yükseltmeyi kısayol üzerinden aktif edip laptop üzerinde ki yetersiz ses sorununu gidermek. Şimdilik karşılaştığım engeller bunlar. Takıldıkça yeni sorularım da olacaktır. Yardımcı olabilen arkadaşlara peşinen teşekkür ederim.

.py

Ses ayarlamanızı aşağıdaki kodu kullanarak yapabilrisiniz.
Sorularınız olursa yardımcı olmaya çalışırım.
import os

os.system('amixer sset Master {}'.format(str(100)))



mhmtkrktr

Amixer 'i mevcut seviyeyi almak için kullanıyorum.  Amixer sadece 100% olan normal seviyeyi ayarlayabiliyor. Hacimsel yükseltmeyi sağlamıyor. O konu sorun değil, sorun olan mesajda belirttiğim şu iki engelin nasıl çözüleceği. Şu ana kadar bulabildiğim neredeyse bütün pygtk belgeleri kopyala yapıştır tarzı, birbirine benzer konulardan ibaret. Yeteri kadar örnekleme yapılamamış sanırım.

bugra9

Kodlarınızda şu şekilde bir düzenleme yaptım. Sanırım yapmak istediklerinizi karşılıyor.


<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window">
    <property name="name">main</property>
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="is_focus">True</property>
    <property name="events">GDK_KEY_PRESS_MASK | GDK_STRUCTURE_MASK</property>
    <property name="opacity">0.28000000000000003</property>
    <property name="margin_top">4</property>
    <property name="border_width">4</property>
    <property name="resizable">False</property>
    <property name="window_position">center-always</property>
    <property name="default_width">150</property>
    <property name="default_height">140</property>
    <property name="skip_taskbar_hint">True</property>
    <property name="focus_on_map">False</property>
    <property name="decorated">False</property>
    <property name="deletable">False</property>
    <property name="gravity">static</property>
    <signal name="key-press-event" handler="on_key_press" swapped="no"/>
    <child>
      <object class="GtkBox" id="popup">
        <property name="name">pop_up</property>
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">2</property>
        <property name="margin_right">2</property>
        <property name="margin_top">2</property>
        <property name="margin_bottom">2</property>
        <property name="orientation">vertical</property>
        <property name="spacing">21</property>
        <property name="baseline_position">bottom</property>
        <child>
          <object class="GtkImage">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="margin_top">10</property>
            <property name="pixel_size">96</property>
            <property name="icon_name">audio-volume-high-symbolic</property>
            <property name="icon_size">1</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkLevelBar" id="progress">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="margin_left">9</property>
            <property name="margin_right">9</property>
            <property name="margin_bottom">10</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <child type="titlebar">
      <placeholder/>
    </child>
  </object>
</interface>




#!/usr/bin/python3

import gi, time, threading
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject

class UI(object):
def __init__(self):
GObject.threads_init()

builder = Gtk.Builder()
builder.add_from_file('volume.ui')
builder.connect_signals(self)

# Hangi elemanı kullanmak, değerleriyle oynamak istiyorsan
# aşağıdaki şekilde elemanları yakala.
self.window = builder.get_object('window')
self.progress = builder.get_object('progress')

self.progress.set_property('value', self.getValue())
self.window.show_all()
self.timer = threading.Timer(3, self.quit)
self.timer.start()

def quit(self):
Gtk.main_quit()
# Eğer uygulamayı kapatmak yerine sadece gizlemek isteniyorsa
#self.window.hide()

def on_key_press(self, args, key):
# Yukarı tuşuna basılırsa
if (key.keyval == 65362):
self.timerReset()
self.progress.set_property('value', self.progress.get_property('value') + 0.1)
# Aşağı tuşuna basılırsa
elif (key.keyval == 65364):
self.timerReset()
self.progress.set_property('value', self.progress.get_property('value') - 0.1)

def timerReset(self):
self.timer.cancel()
self.timer = threading.Timer(3, self.quit)
self.timer.start()

# Göstergeye ilk değer olarak ne koyulacaksa buradan döndürülebilir.
def getValue(self):
return 0.5


app = UI()
Gtk.main()

mhmtkrktr

[mention=632652]@bugra9[/mention] Düzenleme için çok teşekkür ederim. Resmen önümü görmemi sağladı.
Biraz zaman ayırıp, yaptığın düzenleme üzerinden araştırma yapmadan geri dönüş yapmak istemedim.

Şimdilik yapabildiğim kadarıyla şu şekilde oldu. Python dan çok bash scripte benzedi benimkisi ama çalışıyor  :)

#!/usr/bin/python2
# -*- coding: utf-8 -*-
#,
import gi, time, threading, commands, os, sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, Gdk

Vol_Xml="""
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="main_window">
    <property name="name">main</property>
    <property name="can_focus">False</property>
    <property name="is_focus">True</property>
    <property name="has_focus">True</property>
    <property name="events">GDK_KEY_PRESS_MASK | GDK_STRUCTURE_MASK</property>
    <property name="opacity">0.2</property>
    <property name="double_buffered">False</property>
    <property name="resizable">False</property>
    <property name="window_position">center-always</property>
    <property name="default_width">150</property>
    <property name="default_height">140</property>
    <property name="decorated">False</property>
    <property name="deletable">False</property>
    <property name="gravity">static</property>
    <signal name="key-press-event" handler="on_key_press" swapped="yes"/>
    <child>
      <object class="GtkBox" id="popup">
        <property name="name">pop_up</property>
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">2</property>
        <property name="margin_right">2</property>
        <property name="margin_top">2</property>
        <property name="margin_bottom">2</property>
        <property name="orientation">vertical</property>
        <property name="spacing">21</property>
        <property name="baseline_position">bottom</property>
        <child>
          <object class="GtkImage">
            <property name="name">image</property>
            <property name="can_focus">False</property>
            <property name="opacity">0.65</property>
            <property name="halign">center</property>
            <property name="valign">start</property>
            <property name="margin_top">10</property>
            <property name="pixel_size">96</property>
            <property name="icon_name">audio-volume-high-symbolic</property>
            <property name="icon_size">1</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkLevelBar" id="progress">
            <property name="name">levelbar</property>
            <property name="can_focus">False</property>
            <property name="margin_left">9</property>
            <property name="margin_right">9</property>
            <property name="margin_bottom">10</property>
            <property name="max_value">1.5</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
"""

class UI(object):
def __init__(self):
GObject.threads_init()
builder = Gtk.Builder()
builder.add_from_string(Vol_Xml)
builder.connect_signals(self),
self.window = builder.get_object('main_window')
self.progress = builder.get_object('progress')
self.progress.set_property('value', self.getValue())
self.window.show_all()
self.timer = threading.Timer(1, self.quit)
self.timer.start()

def quit(self):
Gtk.main_quit()
# Eğer uygulamayı kapatmak yerine sadece gizlemek isteniyorsa
#self.window.hide()

def on_key_press(self):
Vol_Set = "pactl -- set-sink-volume 0 " + (str(Vol_Stt)+'%')
os.system(Vol_Set)
self.timerReset()
self.progress.set_property('value', self.progress.get_property('value') + 0.1)

def timerReset(self):
self.timer = threading.Timer(1, self.quit)
self.timer.cancel()
self.timer = threading.Timer(1, self.quit)
self.timer.start()

# Göstergeye ilk değer olarak ne koyulacaksa buradan döndürülebilir.
def getValue(self):
status, Vol_Stt = commands.getstatusoutput("LC_ALL=C \
pactl -- list | grep -A11 '^Sink #0' | \
awk '/Volume: front-left:/{print $5}'| \
head -1|cut -d% -f1")
status, Vol_Mt = commands.getstatusoutput("LC_ALL=C \
pactl -- list | grep -A11 '^Sink #0' | \
awk '/Mute/{print $2}'| \
head -1|cut -d% -f1")

global Vol_Stt

if sys.argv[1] == 'up':
if (int(Vol_Stt) < 150):
if str(Vol_Mt) == 'yes':
os.system('pactl -- set-sink-mute 0 0')
Vol_Stt = int(Vol_Stt) + 5
self.on_key_press()

if sys.argv[1] == 'down':
if (int(Vol_Stt) > 4):
Vol_Stt = int(Vol_Stt) - 5
self.on_key_press()
if (int(Vol_Stt) < 4):
if (int(Vol_Stt) != 0):
Vol_Stt = 0
self.on_key_press()
os.system('pactl -- set-sink-mute 0 1')

return (float(Vol_Stt) / 100)
#
css = '''
  * { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition: width 0.5s; }
  #main { background: rgba(250,250,250, .1);
        background-image: linear-gradient(to bottom,rgba(250,250,250, .8),rgba(250,250,250, 65));
        box-shadow: 0 5px 6px rgba(250, 250, 250, 0.9);
  border-width: 1px;
  border: solid transparent;
  border-radius: 6px; }
  #image { background: transparent; }
  #pop_up { background: transparent; }
'''
style_provider = Gtk.CssProvider()
style_provider.load_from_data(css)
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(), style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
app = UI()
Gtk.main()



Eksiklerine gelince;

1 : Uygulama bash scripte olduğu gibi isim.py up ve isim.py down şeklinde tuş ayrımı yapabiliyor. 

key.keyval 'i sadece tekli butonlarda çalıştırabildim. Ctrl + Up\Down gibi birden çok tuşu atayamadım. Şu şekilde listeler var ancak iki tuşun çalıştırıldığı bir örneğe rastlayamadım. http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/key-names.html

Pygtk için şuna benzer örnekler buldum ama çalıştıramadım.
https://gist.github.com/seanh/555602
http://islascruz.org/html/index.php/blog/show/Pygtk%3A-About-keyboard-accelerators.html

Aslında bulduklarımın hepsi çalışıp, benim atadığım "<Control>Up\Down" butonunu ekrana basıyor fakat volume.py içine alınca hata veriyor. Şimdilik beni aşıyor sanırım orası.

2 : Level bar 15% ve üstünde  olması gerektiği gibi çalışıyor. 15% e gelince 0% a kadar sabit kalıyor.

3 : Uyugulama kısayol tuşundan ilk basmada çalışmıyor. 2 defa basıldığında açılıyor. Sonraki her tuş basımında normal işliyor.

4 : Şuan en önemli sorun sanırım bu. Kısayol tuşuna her basmada eski pencerenin üzerine yenisi açılıyor. Süresi dolan arkadan sırayla kapanıyor. Ses değiştirme ve levelbar düzgün çalışıyor. Bunda iki sorun var. İlki görsel olarak hoş görünmüyor, ikincisi tuş basılı tutulursa işlemciyi çok fazla kullanıyor.
Normalde tuş 1 sn içerisinde tekrarlanır veya basılı tutulursa işlemin, açılan ilk pencere üzerinde çalışması gerekiyor. Buna henüz kendimde zaman ayırıp bakamadım ama bu da şuan için beni aşacak gibi görünüyor.

Basit gibi görünse de ilk çalışma için biraz zor bir tercih yaptım sanırım. Butonlar gibi görünen nesneler üzerinde çalışmak daha kolay olabilirdi.  :)




hitokiri

Eğer pencere üzerinde böyle bir şeye kalşıcaksan bunun hiç gereği yok, çünkü shell eklentileri ve gnome-shell bunun için var hatta o yapının ayrı bir yazımı var .js ile.
Alıntı Yaphttps://www.abidibo.net/blog/2016/03/02/how-i-developed-my-first-gnome-shell-extension/
Küçük eklentiler, basit şeyler için bunu kullanabilirsin.

Hatta ikisini birleştirebilirsin şöyle ki; klasik bir progressbarın bir butona bağlı olduğu tipik ses menüsü, ve sesin alçalıp yükseldiğini gösteren notify'ın görünmesi tam da bu değil mi? Genel olarak sistem genelinde yapılan klavye kısayollarını izleme buna atamak için zaten klavye kısayolları var. dconf-editorün bir yerlerinde komut olarak düzenlenebilir bir şeydir, işte sana iki yol;
1. Uygulamını gnome-shell ile birleştir ve progressbar gibi bir şey kullanarak, python için yazdığın komutu notify olarak değerlendir.
2. Bir bash betiği ile klavye tercihlerine dconf ya da her neyse listelerine istediğin gibi bir sistem genelinde çalışan kısayol ekle, ve uygulamanı komut olarak çağır. ;)

Açık olan pencereden de klavye kısayollarını; https://ubuntuforums.org/showthread.php?t=1066357
http://www.pygtk.org/pygtk2tutorial/sec-EventHandling.html
https://forum.ubuntu-tr.net/index.php?topic=34865.0 (Burdaki örnekteki gibi add.event >key press event )

mhmtkrktr

[mention=633015]@hitokiri[/mention] Öneriler için teşekkür ederim.
Az çok gnome-shell eklentisi yazmayı öğrendim gibi ;-)
Burada ki işlevi daha önce bash ile hazırladım ve kullanıyordum zaten. Benim amacım belirttiğim gibi Python ile bir şeyler yapmak. Ayrıca eklenti ile yaparsam sadece Gnome için yapmış olurum. Python ile her sistemde kullanılabilir.
Şimdilik bunu bir kenara bıraktım. Fırsat buldukça daha kolay hazırlanabilecek küçük scriptlerle tecrübe edinmeye çalışıyorum. Yeterli olduğunu düşündüğümde tekrardan kafa yorarım buna.
Yine de bu şekli ile düzeltme yapmak istersen görmek isterim. 

hitokiri

@mhmtkrktr ne yalan söyleyeyim benim uğraşmaya erindiğim bir konu bu, özel düzenlenmiş gui yapıları. Çünkü gün ve gün gelişiyor ve her geçen gün bazı şeyleri kullanılabilir yapmak için, farklı yapılar kullanmak gerekebiliyor. Bir şeyler yapıp ortaya koyma çabası, biraz zor bu açıdan. Bir zamanlar screenlets üzerindeki eklentilerde harika örnekleri vardır bunun, ve python ile yazılmışlardı. Bugün screenlets kullanılmıyor neredeyse, artık eğilim shell ve .js yapısından yana, ama bu yapıyı başka bir şekilde kullanabilirim zaman bulunca, mesela nba maç sonuçlarını veren bir konsol tabanlı uygulama var, arayüz giydirmeye çalışmak oldukça tecrübe kazandıran bir çalışma olabilir, hem bu çalışmanın bir karşılığı da olabilir, kullanılması açısından. :)

mhmtkrktr

Ben kendime, yine kendi iş alanlarımdan biriyle ilgili bir proje buldum. Kiralanacak araçların bakım kaydı, gidiş dönüş zamanları, kira sözleşmeleri, yıllık getirileri gibi bilgileri düzenleyip tutabileceğim bir uygulama. Şimdilik kafayı buna verdim. Yeteri kadar ilerletebilirsem paylaşırım burada. Ses işi şimdilik bir kenarda dursun bakalım ;-)

hitokiri

Masaüstü için düşünüyorsan, https://wiki.python.org/moin/UsingPickle. Pickle müthiş praktiktir, verileri saklayıp yeniden kullanmak açısından.:)

mhmtkrktr

Şimdilik arayüz, istihza ve wep arasında gidip geliyorum. Arayüzün tam olarak nasıl olacağını kararlaştırıp olayı netleştirince tecrübelerinizi paylaşmanızı ayrıca isteyeceğim. Teşekkür ederim.  ;)
https://i.hizliresim.com/8NXB5Q.png