Hlavní navigace

Přepínače, zaškrtávací pole a seznamy v PyQt4

Jan Kaluža

V dnešním článku ze série o knihovně PyQt4 si vylepšíme náš prohlížeč textu z minulého dílu o seznam otevřených souborů. V další části článku pak prohloubíme naše znalosti formulářových prvků dostupných v PyQt4 o užitečný přepínač a často používané zaškrtávací pole.

QListWidget a QListWidgetItem

QListWidget slouží k zobrazení seznamu položek. Každá položka je typu QListWidgetItem. V závislosti na nastavení může uživatel vybírat z QListWidgetu jednu nebo více položek. V této části si povíme nejdříve o funkcích pro vytvoření položek QListWidgetu a pak přejdeme k QListWidgetu samotnému.

QListWidgetItem ( listWidget = None )
QListWidgetItem ( text, listWidget )

Tato funkce vytvoří prázdnou položku, která se zobrazí v QListWidgetu listWidget. Pokud listWidget nezadáme, nezobrazí se položka nikde. V druhé možné syntaxi určíme text položky pomocí proměnné text.

QListWidgetItem­.setText ( text )

Funkcí setText nastavíme text položky QlistWidgetItem.

QListWidgetItem­.setTextAlignment ( alignment )

Touto funkcí nastavíme zarovnání textu v položce. Proměnná alignment je jedna z hodnot QtCore.Qt.Align, o kterých jsme si říkali v minulých dílech.

QListWidgetItem­.setIcon ( qicon )

Fukce nastavuje ikonu položky vytvořenou třídou QIcon().

QListWidgetItem­.setData ( role, qvariant )

Touto funkcí nastavíme položce specifická data. Data položky mají stejný význam jako u položek QComboBoxu, o kterých jsme mluvili v minulém díle. Parametr role udává typ dat. Pro nás je důležité, že pro uživatelská data má proměnná role hodnotu QtCore.Qt.UserRole. Proměnná qvariant je vytvořena funkcí QVariant() a obsahuje samotná data. Přehled všech typů můžeme najít v oficiální dokumentaci (anglicky).

QListWidgetItem­.data ( role )

Funkce vrací data položky ve formátu QVariant. Parametr role udává typ dat. Opět platí, že pro uživatelská data má parametr role hodnotu QtCore.Qt.UserRole.

QListWidget ( parent )

Touto funkcí vytvoříme QListWidget s rodičem parent.

QListWidget.set­SelectionMode ( mode )

Funkce nastavuje typ označování položek. Existují celkem čtyři typy a my si je popíšeme všechny v jedné tabulce.

Typy položek
Hodnota mode Význam
QtGui.QAbstrac­tItemView.NoSe­lection Položky nemohou být označeny.
QtGui.QAbstrac­tItemView.Sin­gleSelection Označena může být vždy jen jedna položka.
QtGui.QAbstrac­tItemView.Mul­tiSelection Označeno může být více položek najednou a označování probíha pomocí kliknutí na položku.
QtGui.QAbstrac­tItemView.Exten­dedSelection Označeno může být více položek najednou, ale pouze pokud uživatel používá k označení položek klávesy ctrl nebo shift.

QListWidget.addItem ( label )

Přidá do QListWidgetu novou položku, která ponese popisek label. Položka je přidána na konec seznamu.

QListWidget.addItem ( item )

Funkce přidá do QListWidgetu novou položku vytvořenou funkcí QListWidgetItem(). Položka je přidána na konec seznamu.

QListWidget.in­sertItem ( row, label )

Funkce vloží do QListWidgetu novou položku s popisem label. Proměnná row udává číslo řádku, na který je nová položka vložena. První řádek seznamu má číslo 0.

QListWidget.in­sertItem ( row, item )

Tato funkce přidá novou položku definovanou proměnnou item do QListWidgetu. Proměnná item je vytvořená pomocí QListWidgetItem(). Proměnná row udává opět číslo řádku, na který je položka vložena.

QListWidget.i­sItemSelected ( item )

Funkce vrací True, pokud je označena položka QListWidgetItem definovaná proměnnou item. V opačném případě vrací funkce False.

QListWidget.item ( row )

Funkce vrací položku, která se nachází na řádku zadaném proměnnou row.

QListWidget.ta­keItem ( row )

Touto funkcí odebereme položku, která se nachází na řádku row, ze seznamu.

QListWidget.sor­tItems ( order = QtCore.Qt.Ascen­dingOrder )

Tato funkce seřadí položky v QListWidgetu. Parametr order určuje způsob řazení a jeho hodnota může být buď QtCore.Qt.Ascen­dingOrder pro řazení podle abecedy vzestupně, nebo QtCore.Qt.Des­cendingOrder pro řazení dle abecedy sestupně.

QListWidget.se­lectedItems ()

Tato funkce vrací seznam (typ list) všech položek QListWidgetu, které jsou označeny.

QListWidget.clear ( )

Funkce smaže všechny položky v QListWidgetu.

QListWidget.i­temActivated ( QListWidgetItem * ) – signál

Signál itemActivated(QLis­tWidgetItem *) je generován, pokud uživatel jakýmkoliv způsobem aktivuje položku. Funkci napojené na signál je předána daná položka.

QListWidget.i­temClicked ( QListWidgetItem * ) – signál

Signál itemClicked(QLis­tWidgetItem *) je generován, pokud uživatel klikne na položku. Funkci napojené na signál je předána daná položka.

QListWidget.i­temDoubleClic­ked ( QListWidgetItem * ) – signál

Signál itemDoubleClic­ked(QListWidge­tItem *) je generován, pokud uživatel provede dvojklik nad položkou QListWidgetu. Funkci napojené na signál je předána daná položka.

QListWidget.i­temSelectionChan­ged () – signál

Signál itemSelection­Changed () je generován, pokud se změnil seznam označených položek QListWidgetu.

QListWidget – Praxe

PyQt 5 1

V praktické části vylepšíme prohlížeč souborů z minulého dílu o QListWidget mainListWidget, který bude zobrazovat seznam otevřených souborů. Po aktivaci položky ze seznamu je zavolána funkce openFile a je jí předána položka (proměnná item), která byla aktivována. Funkce openFile je volána i v případě kliknutí uživatele na tlačítko showPushButton („Zobrazit“). V tomto případě se ovšem funkci openFile nepředá žádný parametr a její proměnná item bude rovna None. Pokud je proměnná item rovna None, je vytvořena nová položka se jménem souboru získaným z QLineEditu fileLineEdit. Jako svá data nese položka celou cestu k soboru. Pokud proměnná item není rovna None, získáme z ní data obsahující celou cestu k souboru. V tomto případě musíme rovněž přepsat QLineEdit fileLineEdit, aby uživatel věděl, který soubor má právě otevřený. Zbytek programu probíhá stějně jako v minulém dílu.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys,os

def openFile(item=None):
    """
    Otevreni souboru a vlozeni jeho obsahu do QTextEditu.
    """
    if item!=None:
        # Nacteni cele cesty k souboru z polozky item
        file=item.data(QtCore.Qt.UserRole)
        file=file.toString()
        # Nastaveni textu QLineEditu
        fileNameLineEdit.setText(file)
    else:
        # Nacteni cele cesty k souboru z QLineEditu
        file=str(fileNameLineEdit.text())
    f=open(file)
    text=f.read()
    # Obsah souboru vlozime do widgetu mainTextEdit
    mainTextEdit.setPlainText(text)
    f.close()
    if item==None:
        # Vytvorime polozku s nazvem souboru
        # Nebudeme zobrazovat jeho cestu, ale pouze jeho basename
        item=QtGui.QListWidgetItem(os.path.basename(file))
        # Cestu k souboru ulozime jako data ke kazde polozce
        item.setData (QtCore.Qt.UserRole, QtCore.QVariant(file))
        # Pridame polozku do seznamu mainListWidget na prvni misto
        mainListWidget.insertItem(0,item)

app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
mainWindow.setWindowTitle("QListWidget")
mainWidget=QtGui.QWidget(mainWindow)
mainWindow.setCentralWidget(mainWidget)
layout=QtGui.QGridLayout(mainWidget)

headerLabel=QtGui.QLabel(u"<h1>Prohlížeč</h1>",mainWidget)
headerLabel.setAlignment(QtCore.Qt.AlignHCenter)

fileNameLabel=QtGui.QLabel("Soubor:",mainWidget)
fileNameLineEdit=QtGui.QLineEdit(mainWidget)

mainTextEdit=QtGui.QTextEdit(mainWidget)
mainTextEdit.setReadOnly(True)

# Vytvorime QListWidget mainListWidget
mainListWidget=QtGui.QListWidget(mainWidget)
# Nastavime maximalni velikost mainListWidgetu
mainListWidget.setMaximumSize(150,65535)

showPushButton=QtGui.QPushButton(u"Zobrazit",mainWidget)
closePushButton=QtGui.QPushButton(u"Zavřít",mainWidget)

# Pridame objekty do layoutu
layout.addWidget(headerLabel,0,0,1,3)
layout.addWidget(mainListWidget,1,0,3,1)
layout.addWidget(fileNameLabel,1,1)
layout.addWidget(fileNameLineEdit,1,2)
layout.addWidget(mainTextEdit,2,1,1,2)
layout.addWidget(showPushButton,3,1)
layout.addWidget(closePushButton,3,2)


# Napojime signal mainListWidgetu na funkci openFile
app.connect(mainListWidget,QtCore.SIGNAL("itemActivated ( QListWidgetItem * )"),openFile)
# Napojime signaly tlacitek
app.connect(closePushButton,QtCore.SIGNAL("clicked ()"),mainWindow.close)
app.connect(showPushButton,QtCore.SIGNAL("clicked ()"),openFile)

mainWindow.show()
sys.exit(app.exec_())

QRadioButton – Teorie

QRadioButton (přepínač) je tlačítko, které se v praxi používá pro výběr jedné z více možností. Může být buď zaškrtnuté nebo nezaškrtnuté. Pokud má jeden rodič (parent) více takových tlačítek, může být zaškrtnuto v jeden moment jen jediné. Pokud potřebujeme použít více nezávislých skupin těchto tlačítek s jedním rodičem, můžeme vytvořit QButtonGroup a pomocí něj tlačítka rozdělit. O QButtonGroupu si povíme na konci článku.

QRadioButton ( parent )
QRadioButton ( text, parent )

Jednou z těchto funkcí vytvoříme QRadioButton. Proměnná parent udává rodiče QRadioButtonu. Proměnná text je popisek přepínače.

QRadioButton.set­Text ( text )

Touto funkcí nastavíme text přepínače.

QRadioButton.set­Checked ( bool )

Pokud je proměnná bool hodnoty True, bude přepínač zaškrtnut.

QRadioButton.is­Checked ( )

Funkce vrací True, pokud je přepínač zaškrtnut. V opačném případě vrací False.

QRadioButton – Praxe

PyQt 5 2

K formuláři z jednoho z předchozích dílů přidáme přepínače pro určení, je-li uživatel muž nebo žena.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys

def send():
   """ Funkce vypisujici udaje formulare vcetne muz/zena """
   name=unicode(nameLineEdit.text())
   surname=unicode(surnameLineEdit.text())
   print "Name: %s, Surname: %s Male: %s" % (name,surname,maleRadioButton.isChecked())

app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
mainWindow.setWindowTitle("QRadioButton")
mainWidget=QtGui.QWidget(mainWindow)
mainWindow.setCentralWidget(mainWidget)
layout=QtGui.QGridLayout(mainWidget)

headerLabel=QtGui.QLabel(u"<h1>Formulář</h1>",mainWidget)
headerLabel.setAlignment(QtCore.Qt.AlignHCenter)

nameLabel=QtGui.QLabel(u"Jméno:",mainWidget)
surnameLabel=QtGui.QLabel(u"Příjmení:",mainWidget)

nameLineEdit=QtGui.QLineEdit(mainWidget)
surnameLineEdit=QtGui.QLineEdit(mainWidget)

# Vytvorime 2 prepinace
maleRadioButton=QtGui.QRadioButton(u"Muž",mainWidget)
femaleRadioButton=QtGui.QRadioButton(u"Žena",mainWidget)

# Jeden z nich zaskrtneme
maleRadioButton.setChecked(True)

sendPushButton=QtGui.QPushButton("Odeslat",mainWidget)
closePushButton=QtGui.QPushButton(u"Zavřít",mainWidget)

# Pridame objekty do layoutu
layout.addWidget(headerLabel,0,0,1,2)
layout.addWidget(nameLabel,1,0)
layout.addWidget(nameLineEdit,1,1)
layout.addWidget(surnameLabel,2,0)
layout.addWidget(surnameLineEdit,2,1)
layout.addWidget(maleRadioButton,3,0)
layout.addWidget(femaleRadioButton,3,1)
layout.addWidget(closePushButton,4,0)
layout.addWidget(sendPushButton,4,1)

# napojime signaly tlacitek
app.connect(closePushButton,QtCore.SIGNAL("clicked ()"),mainWindow.close)
app.connect(sendPushButton,QtCore.SIGNAL("clicked ()"),send)

mainWindow.show()
sys.exit(app.exec_())

QCheckBox – Teorie

QCheckBox je zaškrtávací tlačítko. Pokud chceme tlačítka interně sjednotit, opět je můžeme přidat do QButtonGroupu. QCheckBox má opět dva stavy: zaškrtnutý a nezaškrtnutý.

QCheckBox ( parent )
QCheckBox ( text, parent )

Funkce vytvoří QCheckBox s rodičem parent. Parametr text udává text, který se zobrazí vedle tlačítka.

QCheckBox.setText ( text )

Funkcí setText nastavíme text QCheckBoxu.

QCheckBox.set­Checked ( bool )

Pokud je proměnná bool hodnoty True, bude QCheckBox zaškrtnutý.

QCheckBox.isChecked ( )

Funkce vrací True v případě, že je QCheckBox zaškrtnutý. V opačném případě vrací False.

QCheckBox – Praxe

PyQt 5 3

V praktické části vytvoříme jednoduchý dotazník týkající se používaných distribucí.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys

def send():
   """ Funkce vypisujici udaje formulare """
   # Zjistime o kazdem QCheckBoxu, zda je zaskrtnut
   mandriva=mandrivaCheckBox.isChecked()
   debian=debianCheckBox.isChecked()
   ubuntu=ubuntuCheckBox.isChecked()
   print "Mandriva: %s, Debian: %s Ubuntu: %s" % (mandriva,debian,ubuntu)

app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
mainWindow.setWindowTitle("QCheckBox")
mainWidget=QtGui.QWidget(mainWindow)
mainWindow.setCentralWidget(mainWidget)
layout=QtGui.QGridLayout(mainWidget)

headerLabel=QtGui.QLabel(u"<h1>Dotazník</h1>",mainWidget)
headerLabel.setAlignment(QtCore.Qt.AlignHCenter)

distroLabel=QtGui.QLabel(u"Které distribuce používáte?",mainWidget)

# Vytvorime 3 QCheckBoxy
mandrivaCheckBox=QtGui.QCheckBox(u"Mandriva",mainWidget)
ubuntuCheckBox=QtGui.QCheckBox(u"Ubuntu",mainWidget)
debianCheckBox=QtGui.QCheckBox(u"Debian",mainWidget)

sendPushButton=QtGui.QPushButton("Odeslat",mainWidget)
closePushButton=QtGui.QPushButton(u"Zavřít",mainWidget)

# Pridame objekty do layoutu
layout.addWidget(headerLabel,0,0,1,2)
layout.addWidget(distroLabel,1,0)
layout.addWidget(debianCheckBox,2,0)
layout.addWidget(mandrivaCheckBox,3,0)
layout.addWidget(ubuntuCheckBox,4,0)
layout.addWidget(closePushButton,5,0)
layout.addWidget(sendPushButton,5,1)

# napojime signaly tlacitek
app.connect(closePushButton,QtCore.SIGNAL("clicked ()"),mainWindow.close)
app.connect(sendPushButton,QtCore.SIGNAL("clicked ()"),send)

mainWindow.show()
sys.exit(app.exec_())

QButtonGroup – Teorie

QButtonGroup slouží k virtuálnímu uspořádání tlačítek. Jeho použití se nijak neprojeví na vzhledu programu, ale můžeme pomocí něj interně rozdělit tlačítka do skupin. Hlavně se však používá s QRadioButtonem. Pokud chceme v jednom okně programu zobrazit více na sobě nezávislých skupin přepínačů bez toho, aniž bychom vytvářeli další widgety, použijeme právě QButtonGroup.

QButtonGroup ( parent ) – modul QtGui

Touto funkcí vytvoříme nový QButtonGroup s rodičem parent.

QButtonGroup.ad­dButton ( button )

Tato funkce přidá tlačítko reprezentované proměnnou button do QButtonGroupu. Proměnná button může být jakékoliv tlačítko, přepínač nebo zaškrtávací pole.

QButtonGroup.re­moveButton ( button )

Funkce removeButton odstraňuje tlačítko button z QButtonGroupu.

QButtonGroup.but­tons ()

Tato funkce vrací všechna tlačítka v QButtonGroupu jako seznam (list).

QButtonGroup – Praxe

PyQt 5 4

V praxi si ukážeme již zmiňované použítí s QRadiButtonem. Budeme mít celkem dvě nezávislé skupiny přepínačů v jednom hlavním okně.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys

app = QtGui.QApplication(sys.argv)
mainWindow = QtGui.QMainWindow()
mainWindow.setWindowTitle("QButtonGroup")
mainWidget=QtGui.QWidget(mainWindow)
mainWindow.setCentralWidget(mainWidget)
layout=QtGui.QGridLayout(mainWidget)

# QButtonGroup pro prepinace muz/zena
maleButtonGroup=QtGui.QButtonGroup (mainWidget)

maleRadioButton=QtGui.QRadioButton(u"Muž",mainWidget)
femaleRadioButton=QtGui.QRadioButton(u"Žena",mainWidget)
maleRadioButton.setChecked(True)

# Pridani prepinacu do QButtonGroupu maleButtonGroup
maleButtonGroup.addButton(maleRadioButton)
maleButtonGroup.addButton(femaleRadioButton)

# QButtonGroup pro prepinace tykajici se veku
ageButtonGroup=QtGui.QButtonGroup (mainWidget)

under15RadioButton=QtGui.QRadioButton(u"Mladší než 15 let.",mainWidget)
under18RadioButton=QtGui.QRadioButton(u"Starší než 15 let, mladší než 18.",mainWidget)
over18RadioButton=QtGui.QRadioButton(u"Starší než 18 let.",mainWidget)
over18RadioButton.setChecked(True)

# Pridani prepinacu do QButtonGroupu
ageButtonGroup.addButton(under15RadioButton)
ageButtonGroup.addButton(under18RadioButton)
ageButtonGroup.addButton(over18RadioButton)

closePushButton=QtGui.QPushButton(u"Zavřít",mainWidget)

# Pridame objekty do layoutu
layout.addWidget(maleRadioButton,1,0)
layout.addWidget(femaleRadioButton,1,1)
layout.addWidget(under15RadioButton,2,0)
layout.addWidget(over18RadioButton,2,1)
layout.addWidget(under18RadioButton,3,0,1,2)
layout.addWidget(closePushButton,4,1)

# napojime signaly tlacitek
app.connect(closePushButton,QtCore.SIGNAL("clicked ()"),mainWindow.close)

mainWindow.show()
sys.exit(app.exec_())

Závěr

V dalším díle se naučíme, jak obohatit naše programy o menu a status bar. Dále vytvoříme editor textu ve stylu „Poznámkového bloku“.

Našli jste v článku chybu?
Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

DigiZone.cz: „Black Friday 2016“: závěrečné zhodnocení

„Black Friday 2016“: závěrečné zhodnocení

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

DigiZone.cz: Flix TV startuje i na Slovensku

Flix TV startuje i na Slovensku

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Podnikatel.cz: Zavře krám u #EET Malá pokladna a Teeta?

Zavře krám u #EET Malá pokladna a Teeta?

Vitalia.cz: I církev dnes vyrábí potraviny

I církev dnes vyrábí potraviny

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum

Vitalia.cz: Co pomáhá dítěti při zácpě?

Co pomáhá dítěti při zácpě?

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Podnikatel.cz: Snížení DPH na 15 % se netýká všech

Snížení DPH na 15 % se netýká všech