RkBlog

Hardware, programming and astronomy tutorials and reviews.

QYolk II - Kontenery

Dodajemy obsługę zakładek w aplikacji listujących określoną grupę zainstalowanych pakietów z serwisu pypi (wszystkie, nieaktywne, aktywne)

W tej części kursu zajmiemy się kontenerami ("Containers"). Grupa ta liczy siedem widżetów takich jak karty z zakładkami (Tab Widget) czy Tool Box. W pierwszej części tworzenia GUI dla Yolk otrzymaliśmy taki interfejs:
qyolk5
A naszym celem będzie dodanie karty z trzema zakładkami. Pierwsza zakładka będzie wyświetlała listę wszystkich pakietów (jak obecnie), druga tylko aktywne, a trzecia tylko nieaktywne. W QTDesignerze edytując interfejs wystarczy przeciągnąć "Tab Widget" i umieścić na pierwszej karcie widżet z listą pakietów. Zwróć uwagę że gdy przeciągasz widget nad kartę zakładki to zostanie podświetlone tylko ono. Jeżeli widget przeciągany jest nad okno aplikacji to całe okno zostanie podświetlone:
qyolk6
qyolk7
Widżet trzeba tak przenieść by podświetlona była karta zakładki a nie całe okno (tak by widżet został przypisany do danej karty. Domyślnie przeciągnięty "Tab Widget" ma dwie karty. By dodać trzecią kliknij prawym klawiszem myszy i wybierz opcję "Insert Page". Wybierając po kolei każdą z zakładek będziemy mogli edytować tekst wyświetlany na zakłdce w menu "Property Editor" pod "currentTabText". Na pozostałe dwie karty kopiujemy widżet listy pakietów (CTRL+C i CTRL+V) by otrzymać coś takiego:
qyolk9
qyolk10
QTabWidget nazwałem "pkgTabs", QWidgetTree dla wszystkich pakietów z "treeList" zmieniłem na "allList", QWidgetTree dla aktywnych pakietów nazwałem "activeList", a dla nieaktywnych "notActiveList". Widoczna nad zakładkami edykieta (QLabel) ma nazwę "infoLabel" (i jak na razie nic nie robi). Jeżeli chodzi o start.py to musimy zmienić "treeList" na "allList" oraz dodać w __init__ dodawanie danych do pozostałych list:
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from qyolk import Ui_QYolk
from yolk import yolklib

class StartQT4(QtGui.QMainWindow):
	def __init__(self, parent=None):
		QtGui.QWidget.__init__(self, parent)
		self.ui = Ui_QYolk()
		self.ui.setupUi(self)
		# set the widths of the columns
		################
		# All packages
		################
		self.ui.allList.setColumnWidth(0,200)
		self.ui.allList.setColumnWidth(1,100)
		# generator which retuns list of installed packages
		packages = yolklib.Distributions()
		for pkg in packages.get_distributions('all'):
			a = QtGui.QTreeWidgetItem(self.ui.allList)
			pk = str(pkg[0]).split(' ')
			if pkg[1]:
				status = 'Active'
			else:
				status = 'Not Active'
				a.setTextColor(0, QtGui.QColor(128, 128, 128))
				a.setTextColor(1, QtGui.QColor(128, 128, 128))
				a.setTextColor(2, QtGui.QColor(128, 128, 128))
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, status)
		################
		# Active Packages
		################
		# set the widths of the columns
		self.ui.activeList.setColumnWidth(0,200)
		self.ui.activeList.setColumnWidth(1,100)
		# generator which retuns list of active packages
		for pkg in packages.get_distributions('active'):
			a = QtGui.QTreeWidgetItem(self.ui.activeList)
			pk = str(pkg[0]).split(' ')
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, 'Active')
		################
		# Not Active Packages
		################
		# set the widths of the columns
		self.ui.notActiveList.setColumnWidth(0,200)
		self.ui.notActiveList.setColumnWidth(1,100)
		# generator which retuns list of not active packages
		for pkg in packages.get_distributions('nonactive'):
			a = QtGui.QTreeWidgetItem(self.ui.notActiveList)
			pk = str(pkg[0]).split(' ')
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, 'Not Active')
	
if __name__ == "__main__":
	app = QtGui.QApplication(sys.argv)
	myapp = StartQT4()
	myapp.show()
	sys.exit(app.exec_())
I gotowe:
qyolk8

Sygnały i sloty z parametrami

QTabWidget ma sygnał currentChanged wysyłany gdy wybierzemy inną zakładkę. Zwróć uwagę na zapis:
void currentChanged (int)
Ten sygnał zawiera parametr (liczba całkowita). Dotychczas używane przez nas sygnały nie miały parametrów. W przypadku tego sygnału ową liczbą będzie identyfikator zakładki - numerowane od zera. Sygnał ze slotem łączymy normalnie podając również "(int)" (dokładny zapis z dokumentacji):
QtCore.QObject.connect(self.ui.pkgTabs,QtCore.SIGNAL("currentChanged(int)"), self.tab_change)
def tab_change(self, tab_id):
	print tab_id
tab_id to nazwa zmiennej (wymyślona przez nas), która przyjmie wartość zmiennej sygnału (odpowiednio pierwsza zmienna sygnału przechodzi na pierwszą zmienną slotu i tak samo z kolejnymi). Jako że mamy trzy zakładki to możemy otrzymać 0, 1 lub 2. Do czego można wykorzystać ten sygnał ? A do zmiany tekstu etykiety "infoLabel":
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from qyolk import Ui_QYolk
from yolk import yolklib

class StartQT4(QtGui.QMainWindow):
	def __init__(self, parent=None):
		QtGui.QWidget.__init__(self, parent)
		self.ui = Ui_QYolk()
		self.ui.setupUi(self)
		# set the widths of the columns
		################
		# All packages
		################
		self.ui.allList.setColumnWidth(0,200)
		self.ui.allList.setColumnWidth(1,100)
		# generator which retuns list of installed packages
		packages = yolklib.Distributions()
		for pkg in packages.get_distributions('all'):
			a = QtGui.QTreeWidgetItem(self.ui.allList)
			pk = str(pkg[0]).split(' ')
			if pkg[1]:
				status = 'Active'
			else:
				status = 'Not Active'
				a.setTextColor(0, QtGui.QColor(128, 128, 128))
				a.setTextColor(1, QtGui.QColor(128, 128, 128))
				a.setTextColor(2, QtGui.QColor(128, 128, 128))
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, status)
		################
		# Active Packages
		################
		# set the widths of the columns
		self.ui.activeList.setColumnWidth(0,200)
		self.ui.activeList.setColumnWidth(1,100)
		# generator which retuns list of active packages
		for pkg in packages.get_distributions('active'):
			a = QtGui.QTreeWidgetItem(self.ui.activeList)
			pk = str(pkg[0]).split(' ')
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, 'Active')
		################
		# Not Active Packages
		################
		# set the widths of the columns
		self.ui.notActiveList.setColumnWidth(0,200)
		self.ui.notActiveList.setColumnWidth(1,100)
		# generator which retuns list of not-active packages
		for pkg in packages.get_distributions('nonactive'):
			a = QtGui.QTreeWidgetItem(self.ui.notActiveList)
			pk = str(pkg[0]).split(' ')
			a.setText(0, pk[0])
			a.setText(1, pk[1])
			a.setText(2, 'Not Active')
		
		# Signals
		QtCore.QObject.connect(self.ui.pkgTabs,QtCore.SIGNAL("currentChanged(int)"), self.tab_change)
	def tab_change(self, tab_id):
		if tab_id == 0:
			self.ui.infoLabel.setText('<b>QYolk</b>: Browsing all installed cheeseshop packages')
		elif tab_id == 1:
			self.ui.infoLabel.setText('<b>QYolk</b>: Browsing active packages')
		elif tab_id == 2:
			self.ui.infoLabel.setText('<b>QYolk</b>: Browsing not active packages (older versions)')
	
if __name__ == "__main__":
	app = QtGui.QApplication(sys.argv)
	myapp = StartQT4()
	myapp.show()
	sys.exit(app.exec_())
Dodałem połączenie sygnału ze slotem oraz metodę "tab_change" zmieniającej tekst etykiety za pomocą self.ui.infoLabel.setText w zależności od wartości "tab_id". Nasza aplikacja umie coraz więcej. W kolejnych częściach dodamy kolejne funkcjonalności.

Źródła

Pobierz źródła
RkBlog

PyQt, 14 July 2008,

Comment article