Grafik interfeys nima uçun kerak?
Hozirgaça yozgan dasturlarimiz terminalda işladi: matn çiqardi va input() orqali javob kutdi. Dasturçi uçun bu qulay, lekin oddiy foydalanuvçi oynalar, tugmalar va menyularga örgangan. Bunday interfeys GUI (Graphical User Interface — grafik foydalanuvçi interfeysi) deb ataladi.
Python da GUI yoziş uçun bir neçta kutubxona bor:
| Kutubxona | Xususiyati |
|---|---|
tkinter | Python bilan birga keladi, oddiy, lekin körinişi biroz eskiça |
PySide6 | Qt 6 ning rasmiy Python versiyasi, zamonaviy va kuçli, LGPL litsenziyasi |
PyQt6 | Xuddi şu Qt 6 uçun boşqa kompaniya tayyorlagan versiya, GPL yoki tijoriy litsenziya |
Kivy, Flet | Mobil va sensorli ekranlarga möljallangan |
Bu bobda PySide6 ni tanlaymiz. Qt — dunyodagi eng maşhur GUI freymvorklaridan biri, unda yozilgan ilovalar Windows, macOS va Linux da bir xil işlaydi. PySide6 — Qt for Python loyihasining kutubxonasi, uni Qt ni işlab çiquvçi kompaniyaning özi qöllab-quvvatlaydi. Avvalgi avlod kutubxonasi PyQt5 edi; endi yangi loyihalar uçun PySide6 yoki PyQt6 tavsiya etiladi.
Bu bobdagi misollar brauzerda işlamaydi (ular haqiqiy oyna oçadi), şuning uçun ularni öz kompyuteringizda işga tuşiring.
Örnatiş
PySide6 ni virtual muhitga örnatiş tavsiya etiladi:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install PySide6
Tekşirib köriş uçun:
python -c "import PySide6; print(PySide6.__version__)"
Birinçi oyna
Har qanday Qt ilovasi uçta qismdan iborat: bitta QApplication obyekti, kamida bitta oyna (vidjet) va hodisalar sikli (event loop). Hodisalar sikli — app.exec() çaqirilganda boşlanadigan çeksiz aylaniş: u siçqonça bosilişi, klaviatura, oynani yopiş kabi hodisalarni kutadi va kerakli funksiyani çaqiradi.
import sys
from PySide6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
oyna = QWidget()
oyna.setWindowTitle("Mening birinçi oynam")
oyna.resize(400, 250)
oyna.show()
sys.exit(app.exec())
sys.argv ni QApplication ga beriş anʼanaviy usul: Qt buyruq qatoridagi ayrim parametrlarni özi tuşunadi. sys.exit(app.exec()) esa oyna yopilganda dastur töğri çiqiş kodi bilan tugaşini taʼminlaydi.
Vidjetlar va QLabel
Qt da ekrandagi har bir element — vidjet (QWidget dan meros olgan klass). Yorliq QLabel, tugma QPushButton, matn maydoni QLineEdit va hokazo. Oynani odatda QWidget dan meros olgan klass sifatida yozamiz — şunda barça vidjetlar va funksiyalar bir joyda turadi:
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget
class SalomOyna(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Salom")
sarlavha = QLabel("Assalomu alaykum!")
sarlavha.setAlignment(Qt.AlignmentFlag.AlignCenter)
shrift = sarlavha.font()
shrift.setPointSize(20)
sarlavha.setFont(shrift)
izoh = QLabel("Bu oyna PySide6 yordamida yaratildi.")
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(sarlavha)
joylashuv.addWidget(izoh)
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = SalomOyna()
oyna.show()
sys.exit(app.exec())
QVBoxLayout (vertikal joylaşuv) haqida quyida batafsil gaplaşamiz — hozirça u vidjetlarni ustma-ust tizişini bilsangiz yetarli.
Tugmalar, signallar va slotlar
Qt ning eng muhim ğoyasi — signal va slot. Vidjet biror hodisa yuz berganda signal çiqaradi (masalan, tugma bosilganda clicked). Siz bu signalni istalgan funksiyaga — slot ga — ulaysiz. Signal çiqqanda Qt öşa funksiyani avtomatik çaqiradi.
Bu xuddi eşik qönğiroğiga öxşaydi: qönğiroq (signal) kim eşitişini bilmaydi, siz esa unga «jiringlasa, eşikni oç» degan vazifani (slot) boğlab qöyasiz.
import sys
from PySide6.QtCore import Slot
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
class Hisoblagich(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Hisoblagiç")
self.son = 0
self.yorliq = QLabel("Bosişlar soni: 0")
tugma = QPushButton("Bosing!")
nol_tugma = QPushButton("Nolga qaytariş")
# Signalni slotga ulaymiz
tugma.clicked.connect(self.oshir)
nol_tugma.clicked.connect(self.nolla)
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(self.yorliq)
joylashuv.addWidget(tugma)
joylashuv.addWidget(nol_tugma)
@Slot()
def oshir(self) -> None:
self.son += 1
self.yorliq.setText(f"Bosişlar soni: {self.son}")
@Slot()
def nolla(self) -> None:
self.son = 0
self.yorliq.setText("Bosişlar soni: 0")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Hisoblagich()
oyna.show()
sys.exit(app.exec())
Eʼtibor bering: connect(self.oshir) — funksiyaning özini beramiz, self.oshir() deb çaqirmaymiz. @Slot() dekoratori majburiy emas, lekin u kodni aniqroq qiladi va biroz tezlik beradi.
Matn kiritiş: QLineEdit
QLineEdit — bir qatorli matn maydoni. Undagi matnni text() bilan öqiymiz, setText() bilan yozamiz. Foydali signallari: textChanged (har bir harf özgarganda) va returnPressed (Enter bosilganda). Quyida valyuta kalkulyatori — dollarni sömga aylantiradi:
import sys
from PySide6.QtWidgets import (
QApplication, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget,
)
KURS = 12_800 # 1 dollar neça söm (misol uçun)
class Valyuta(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Valyuta kalkulyatori")
self.maydon = QLineEdit()
self.maydon.setPlaceholderText("Dollar miqdorini kiriting")
self.natija = QLabel("Natija şu yerda çiqadi")
tugma = QPushButton("Hisoblaş")
tugma.clicked.connect(self.hisobla)
self.maydon.returnPressed.connect(self.hisobla) # Enter ham işlaydi
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(QLabel(f"Kurs: 1 $ = {KURS:,} söm"))
joylashuv.addWidget(self.maydon)
joylashuv.addWidget(tugma)
joylashuv.addWidget(self.natija)
def hisobla(self) -> None:
matn = self.maydon.text().replace(",", ".").strip()
try:
dollar = float(matn)
except ValueError:
self.natija.setText("Iltimos, son kiriting")
return
self.natija.setText(f"{dollar:,.2f} $ = {dollar * KURS:,.0f} söm")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Valyuta()
oyna.show()
sys.exit(app.exec())
Foydalanuvçi har doim ham töğri qiymat kiritmaydi, şuning uçun try/except bilan himoyalaniş GUI dasturlarida ayniqsa muhim — aks holda xato butun ilovani yopib qöyişi mumkin.
Köp qatorli matn: QTextEdit
QTextEdit — köp qatorli matn muharriri. Oddiy matn uçun toPlainText() va setPlainText() metodlaridan foydalanamiz. Quyidagi misol yozilgan matndagi söz va belgilar sonini jonli hisoblaydi:
import sys
from PySide6.QtWidgets import QApplication, QLabel, QTextEdit, QVBoxLayout, QWidget
class SozSanagich(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Söz sanagiç")
self.resize(450, 300)
self.muharrir = QTextEdit()
self.muharrir.setPlaceholderText("Matningizni şu yerga yozing...")
self.holat = QLabel("Sözlar: 0 | Belgilar: 0")
self.muharrir.textChanged.connect(self.yangila)
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(self.muharrir)
joylashuv.addWidget(self.holat)
def yangila(self) -> None:
matn = self.muharrir.toPlainText()
self.holat.setText(f"Sözlar: {len(matn.split())} | Belgilar: {len(matn)}")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = SozSanagich()
oyna.show()
sys.exit(app.exec())
Tanlov vidjetlari: QCheckBox va QRadioButton
QCheckBox— belgilaş katakçasi: bir neçtasini bir vaqtda tanlaş mumkin. HolatiisChecked()bilan tekşiriladi.QRadioButton— bir guruh içida faqat bittasi tanlanadi. Bir xil ota-vidjet içidagi radiotugmalar avtomatik guruhlanadi; aniqroq boşqariş uçunQButtonGroupişlatiladi.
Kiçik kafe buyurtma oynasini yasaymiz:
import sys
from PySide6.QtWidgets import (
QApplication, QButtonGroup, QCheckBox, QLabel, QPushButton,
QRadioButton, QVBoxLayout, QWidget,
)
ICHIMLIKLAR = {"Çoy": 5_000, "Qahva": 15_000, "Kompot": 8_000}
QOSHIMCHALAR = {"Şakar": 0, "Limon": 2_000, "Pişiriq": 12_000}
class Buyurtma(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Kafe buyurtmasi")
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(QLabel("Içimlik tanlang:"))
self.guruh = QButtonGroup(self)
for i, nom in enumerate(ICHIMLIKLAR):
radio = QRadioButton(nom)
if i == 0:
radio.setChecked(True)
self.guruh.addButton(radio)
joylashuv.addWidget(radio)
joylashuv.addWidget(QLabel("Qöşimçalar:"))
self.katakchalar: list[QCheckBox] = []
for nom in QOSHIMCHALAR:
katak = QCheckBox(nom)
self.katakchalar.append(katak)
joylashuv.addWidget(katak)
tugma = QPushButton("Hisoblaş")
tugma.clicked.connect(self.hisobla)
self.natija = QLabel()
joylashuv.addWidget(tugma)
joylashuv.addWidget(self.natija)
def hisobla(self) -> None:
ichimlik = self.guruh.checkedButton().text()
jami = ICHIMLIKLAR[ichimlik]
tanlangan = [k.text() for k in self.katakchalar if k.isChecked()]
jami += sum(QOSHIMCHALAR[nom] for nom in tanlangan)
royxat = ", ".join([ichimlik, *tanlangan])
self.natija.setText(f"{royxat}\nJami: {jami:,} söm")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Buyurtma()
oyna.show()
sys.exit(app.exec())
Joylaşuvlar: QVBoxLayout va QHBoxLayout
Vidjetlarni piksel koordinatalari bilan (move(10, 20)) joylaştiriş mumkin, lekin bu yomon odat: oyna kattalaşganda yoki boşqa tilga tarjima qilinganda hamma narsa buziladi. Buning örniga joylaşuv menejerlari (layout) işlatiladi — ular vidjetlarni özi tartiblaydi va ölçamini moslaydi.
| Joylaşuv | Vazifasi |
|---|---|
QVBoxLayout | Vidjetlarni yuqoridan pastga tizadi |
QHBoxLayout | Vidjetlarni çapdan öngga tizadi |
QGridLayout | Jadval (qator va ustun) körinişida joylaydi |
QFormLayout | «Yorliq — maydon» juftliklari uçun qulay |
Joylaşuvlarni bir-birining içiga joylaş mumkin: masalan, vertikal joylaşuv içida tugmalar qatori uçun gorizontal joylaşuv. addStretch() esa böş «prujina» qöşadi — u elementlarni bir tomonga surib turadi.
import sys
from PySide6.QtWidgets import (
QApplication, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget,
)
class Anketa(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Joylaşuvlar")
asosiy = QVBoxLayout(self)
for yorliq in ("Ism:", "Familiya:", "Şahar:"):
qator = QHBoxLayout()
nom = QLabel(yorliq)
nom.setFixedWidth(70)
qator.addWidget(nom)
qator.addWidget(QLineEdit())
asosiy.addLayout(qator)
tugmalar = QHBoxLayout()
tugmalar.addStretch() # tugmalarni öng tomonga suradi
tugmalar.addWidget(QPushButton("Bekor qiliş"))
tugmalar.addWidget(QPushButton("Saqlaş"))
asosiy.addStretch()
asosiy.addLayout(tugmalar)
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Anketa()
oyna.resize(380, 200)
oyna.show()
sys.exit(app.exec())
Oynani siçqonça bilan kattalaştirib köring: matn maydonlari kengayadi, tugmalar esa öng pastki burçakda qoladi.
Menyular va QMainWindow
Haqiqiy ilovalarda odatda menyu satri, asboblar paneli va holat satri böladi. Bularning hammasi QMainWindow klassida tayyor. Menyu bandlari QAction obyektlari orqali yaratiladi: har bir QAction ning matni, tezkor tugmasi va triggered signali bor.
import sys
from PySide6.QtGui import QAction, QKeySequence
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QMessageBox
class AsosiyOyna(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Menyu namunasi")
self.setCentralWidget(QLabel("Menyudan biror bandni tanlang"))
fayl_menyu = self.menuBar().addMenu("&Fayl")
chiqish = QAction("&Çiqiş", self)
chiqish.setShortcut(QKeySequence.StandardKey.Quit)
chiqish.triggered.connect(self.close)
fayl_menyu.addAction(chiqish)
yordam_menyu = self.menuBar().addMenu("&Yordam")
haqida = QAction("Dastur &haqida", self)
haqida.triggered.connect(self.haqida_oyna)
yordam_menyu.addAction(haqida)
self.statusBar().showMessage("Tayyor")
def haqida_oyna(self) -> None:
QMessageBox.information(self, "Dastur haqida", "PySide6 menyu namunasi, 1.0-versiya")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = AsosiyOyna()
oyna.resize(500, 300)
oyna.show()
sys.exit(app.exec())
Menyu matnidagi & belgisi keyingi harfni Alt bilan işlaydigan tezkor harfga aylantiradi (masalan, Alt+F — «Fayl»). QKeySequence.StandardKey.Quit esa har bir operatsion tizimdagi odatiy tugmalar birikmasini özi tanlaydi.
Amaliy loyiha: mini bloknot
Endi örganganlarimizni birlaştirib, fayllarni oçib-saqlaydigan kiçik bloknot yasaymiz. Yangi narsalar:
QFileDialog.getOpenFileName()vagetSaveFileName()— tizimning standart fayl tanlaş oynalari. Ular(yoʻl, filtr)juftligini qaytaradi; foydalanuvçi bekor qilsa, yöl böş satr böladi.pathlib.Pathbilan faylniutf-8kodlaşda öqiş va yoziş.document().isModified()— matn saqlanmaganini biliş va oyna yopilayotganda (closeEvent) ogohlantiriş.
import sys
from pathlib import Path
from PySide6.QtGui import QAction, QCloseEvent, QKeySequence
from PySide6.QtWidgets import (
QApplication, QFileDialog, QMainWindow, QMessageBox, QTextEdit,
)
FILTR = "Matn fayllari (*.txt);;Barça fayllar (*)"
class Bloknot(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.joriy_fayl: Path | None = None
self.muharrir = QTextEdit()
self.muharrir.setAcceptRichText(False) # faqat oddiy matn
self.setCentralWidget(self.muharrir)
self.menyu_yarat()
self.sarlavhani_yangila()
self.muharrir.document().modificationChanged.connect(self.sarlavhani_yangila)
def menyu_yarat(self) -> None:
menyu = self.menuBar().addMenu("&Fayl")
bandlar = [
("&Yangi", QKeySequence.StandardKey.New, self.yangi),
("&Oçiş...", QKeySequence.StandardKey.Open, self.ochish),
("&Saqlaş", QKeySequence.StandardKey.Save, self.saqlash),
("&Boşqa nom bilan saqlaş...", QKeySequence.StandardKey.SaveAs, self.boshqa_nomda),
]
for matn, tugma, funksiya in bandlar:
amal = QAction(matn, self)
amal.setShortcut(tugma)
amal.triggered.connect(funksiya)
menyu.addAction(amal)
menyu.addSeparator()
chiqish = QAction("&Çiqiş", self)
chiqish.triggered.connect(self.close)
menyu.addAction(chiqish)
def sarlavhani_yangila(self) -> None:
nom = self.joriy_fayl.name if self.joriy_fayl else "Nomsiz"
belgi = "*" if self.muharrir.document().isModified() else ""
self.setWindowTitle(f"{belgi}{nom} — Bloknot")
def davom_etsinmi(self) -> bool:
"""Saqlanmagan özgariş bölsa, foydalanuvçidan söraydi."""
if not self.muharrir.document().isModified():
return True
javob = QMessageBox.question(
self, "Bloknot", "Özgarişlar saqlanmagan. Saqlansinmi?",
QMessageBox.StandardButton.Save
| QMessageBox.StandardButton.Discard
| QMessageBox.StandardButton.Cancel,
)
if javob == QMessageBox.StandardButton.Save:
return self.saqlash()
return javob == QMessageBox.StandardButton.Discard
def yangi(self) -> None:
if self.davom_etsinmi():
self.muharrir.clear()
self.joriy_fayl = None
self.muharrir.document().setModified(False)
self.sarlavhani_yangila()
def ochish(self) -> None:
if not self.davom_etsinmi():
return
yol, _ = QFileDialog.getOpenFileName(self, "Faylni oçiş", "", FILTR)
if not yol:
return # foydalanuvçi bekor qildi
try:
matn = Path(yol).read_text(encoding="utf-8")
except (OSError, UnicodeDecodeError) as xato:
QMessageBox.warning(self, "Xato", f"Faylni öqib bölmadi:\n{xato}")
return
self.muharrir.setPlainText(matn)
self.joriy_fayl = Path(yol)
self.muharrir.document().setModified(False)
self.sarlavhani_yangila()
def saqlash(self) -> bool:
if self.joriy_fayl is None:
return self.boshqa_nomda()
return self.faylga_yoz(self.joriy_fayl)
def boshqa_nomda(self) -> bool:
yol, _ = QFileDialog.getSaveFileName(self, "Saqlaş", "matn.txt", FILTR)
if not yol:
return False
return self.faylga_yoz(Path(yol))
def faylga_yoz(self, yol: Path) -> bool:
try:
yol.write_text(self.muharrir.toPlainText(), encoding="utf-8")
except OSError as xato:
QMessageBox.warning(self, "Xato", f"Saqlab bölmadi:\n{xato}")
return False
self.joriy_fayl = yol
self.muharrir.document().setModified(False)
self.statusBar().showMessage(f"Saqlandi: {yol}", 3000)
self.sarlavhani_yangila()
return True
def closeEvent(self, event: QCloseEvent) -> None:
if self.davom_etsinmi():
event.accept()
else:
event.ignore() # oyna yopilmaydi
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Bloknot()
oyna.resize(700, 500)
oyna.show()
sys.exit(app.exec())
Bu kodda bir neçta yaxşi odatlar bor: fayl bilan işlaş try/except içida, foydalanuvçi «Bekor qiliş» tugmasini bossa dastur jim qaytadi, saqlanmagan matn esa tasodifan yöqolmaydi. Sarlavhadagi * belgisi ham köplab muharrirlarda qabul qilingan anʼana.
Amaliy loyiha: kiriş formasi
Oxirgi misolda login va parol söraydigan kiriş oynasini yasaymiz. Unda QFormLayout, parolni yulduzçalar bilan yaşiradigan QLineEdit.EchoMode.Password rejimi, «parolni körsatiş» katakçasi va urinişlar sonini çeklaş bor.
import hashlib
import sys
from PySide6.QtWidgets import (
QApplication, QCheckBox, QFormLayout, QLabel, QLineEdit,
QMessageBox, QPushButton, QVBoxLayout, QWidget,
)
# Haqiqiy dasturda parollar oçiq holda emas, xeş körinişida saqlanadi
FOYDALANUVCHILAR = {
"aziza": hashlib.sha256("parol123".encode()).hexdigest(),
}
MAKS_URINISH = 3
class KirishOynasi(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Tizimga kiriş")
self.urinishlar = 0
self.login = QLineEdit()
self.login.setPlaceholderText("masalan: aziza")
self.parol = QLineEdit()
self.parol.setEchoMode(QLineEdit.EchoMode.Password)
self.korsat = QCheckBox("Parolni körsatiş")
self.korsat.toggled.connect(self.parol_rejimi)
forma = QFormLayout()
forma.addRow("Login:", self.login)
forma.addRow("Parol:", self.parol)
forma.addRow("", self.korsat)
self.xabar = QLabel()
self.tugma = QPushButton("Kiriş")
self.tugma.setDefault(True)
self.tugma.clicked.connect(self.tekshir)
self.parol.returnPressed.connect(self.tekshir)
asosiy = QVBoxLayout(self)
asosiy.addLayout(forma)
asosiy.addWidget(self.xabar)
asosiy.addWidget(self.tugma)
def parol_rejimi(self, belgilangan: bool) -> None:
rejim = QLineEdit.EchoMode.Normal if belgilangan else QLineEdit.EchoMode.Password
self.parol.setEchoMode(rejim)
def tekshir(self) -> None:
login = self.login.text().strip().lower()
xesh = hashlib.sha256(self.parol.text().encode()).hexdigest()
if not login or not self.parol.text():
self.xabar.setText("Login va parolni kiriting")
return
if FOYDALANUVCHILAR.get(login) == xesh:
QMessageBox.information(self, "Xuş kelibsiz", f"Salom, {login}!")
self.close()
return
self.urinishlar += 1
qoldi = MAKS_URINISH - self.urinishlar
self.parol.clear()
if qoldi == 0:
self.xabar.setText("Urinişlar tugadi. Keyinroq qayta urinib köring.")
self.tugma.setEnabled(False)
else:
self.xabar.setText(f"Login yoki parol notöğri. Yana {qoldi} ta uriniş qoldi.")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = KirishOynasi()
oyna.show()
sys.exit(app.exec())
Xato xabarida «login yoki parol notöğri» deb umumiy yozilgani ham bejiz emas: qaysi biri xato ekanini aytsangiz, buzğunçiga mavjud loginlarni topişda yordam bergan bölasiz.
Köp uçraydigan xatolar
GUI dasturlaşni endi boşlaganlar odatda bir xil tuzoqlarga tuşadi. Ularni oldindan bilsangiz, köp vaqtingiz tejaladi:
- Funksiyani çaqirib yuboriş.
tugma.clicked.connect(self.oshir())deb yozsangiz, funksiya darhol bir marta bajariladi va uning natijasi (None) ulanadi. Töğrisi — qavslarsiz:connect(self.oshir). - Vidjetni özgaruvçida saqlamaslik. Oynani funksiya içida yaratib,
selfga yoki taşqi özgaruvçiga saqlamasangiz, Python uni «keraksiz» deb öçirib yuborişi mumkin — oyna bir lahza körinib, yöqoladi. app.exec()ni unutiş. Hodisalar sikli boşlanmasa, oyna oçilib darhol yopiladi.- Uzoq işni asosiy oqimda bajariş. Tugma bosilganda katta faylni yuklaş yoki internetdan maʼlumot oliş kabi uzoq amal bajarilsa, şu vaqt davomida oyna «qotib» qoladi. Bunday işlar uçun
QThreadyokiQThreadPoolişlatiladi — bu keyingi bosqiç mavzusi. - Koordinatalar bilan joylaştiriş. Turli ekran ölçamlari va şriftlarda interfeys buzilmasligi uçun doim joylaşuv menejerlaridan foydalaning.
Xulosa
PySide6—Qt 6ning rasmiy,LGPLlitsenziyali Python kutubxonasi;PyQt6—GPL/tijoriy muqobili.- Har bir ilova:
QApplication+ oyna +app.exec()(hodisalar sikli). - Signal va slot:
tugma.clicked.connect(funksiya)— funksiyani çaqirmasdan uzatamiz. QLabel,QPushButton,QLineEdit,QTextEdit,QCheckBox,QRadioButton— asosiy vidjetlar.- Vidjetlarni koordinata bilan emas,
QVBoxLayout,QHBoxLayout,QFormLayoutbilan joylaştiring. QMainWindowmenyu va holat satrini beradi; menyu bandlari —QAction.QFileDialogvaQMessageBoxstandart dialog oynalarini tayyor holda taqdim etadi.
Maşqlar
- Ikki
QLineEditva törtta tugma (+,-,*,/) dan iborat oddiy kalkulyator yozing. NatijaQLabelda çiqsin, nolga bölişda xabar bersin.
Yeçim
import sys
from PySide6.QtWidgets import (
QApplication, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget,
)
class Kalkulyator(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Kalkulyator")
self.a = QLineEdit()
self.b = QLineEdit()
self.natija = QLabel("Natija: -")
tugmalar = QHBoxLayout()
for belgi in "+-*/":
tugma = QPushButton(belgi)
tugma.clicked.connect(lambda _=False, b=belgi: self.hisobla(b))
tugmalar.addWidget(tugma)
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(self.a)
joylashuv.addWidget(self.b)
joylashuv.addLayout(tugmalar)
joylashuv.addWidget(self.natija)
def hisobla(self, amal: str) -> None:
try:
x, y = float(self.a.text()), float(self.b.text())
except ValueError:
self.natija.setText("Iltimos, son kiriting")
return
match amal:
case "+": javob = x + y
case "-": javob = x - y
case "*": javob = x * y
case "/":
if y == 0:
self.natija.setText("Nolga bölib bölmaydi")
return
javob = x / y
self.natija.setText(f"Natija: {javob:g}")
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Kalkulyator()
oyna.show()
sys.exit(app.exec())
- Hisoblagiç misolini özgartiring: «Kamaytiriş» tugmasini qöşing va son 0 dan pastga tuşmasin (0 bölganda tugma
setEnabled(False)bilan öçirilsin).
Yeçim
import sys
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
class Hisoblagich(QWidget):
def __init__(self) -> None:
super().__init__()
self.son = 0
self.yorliq = QLabel()
oshir = QPushButton("Oşiriş")
self.kamaytir_tugma = QPushButton("Kamaytiriş")
oshir.clicked.connect(lambda: self.ozgartir(1))
self.kamaytir_tugma.clicked.connect(lambda: self.ozgartir(-1))
joylashuv = QVBoxLayout(self)
joylashuv.addWidget(self.yorliq)
joylashuv.addWidget(oshir)
joylashuv.addWidget(self.kamaytir_tugma)
self.ozgartir(0)
def ozgartir(self, qadam: int) -> None:
self.son = max(0, self.son + qadam)
self.yorliq.setText(f"Son: {self.son}")
self.kamaytir_tugma.setEnabled(self.son > 0)
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Hisoblagich()
oyna.show()
sys.exit(app.exec())
- Mini bloknotga «Tahrirlaş» menyusini qöşing: «Bekor qiliş» (
undo), «Qaytariş» (redo) va «Hammasini tanlaş» (selectAll).QTextEditda bu metodlar tayyor mavjud.
Yeçim
import sys
from PySide6.QtGui import QAction, QKeySequence
from PySide6.QtWidgets import QApplication, QMainWindow, QTextEdit
class Bloknot(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Bloknot")
self.muharrir = QTextEdit()
self.setCentralWidget(self.muharrir)
menyu = self.menuBar().addMenu("&Tahrirlaş")
bandlar = [
("Bekor qiliş", QKeySequence.StandardKey.Undo, self.muharrir.undo),
("Qaytariş", QKeySequence.StandardKey.Redo, self.muharrir.redo),
("Hammasini tanlaş", QKeySequence.StandardKey.SelectAll, self.muharrir.selectAll),
]
for matn, tugma, funksiya in bandlar:
amal = QAction(matn, self)
amal.setShortcut(tugma)
amal.triggered.connect(funksiya)
menyu.addAction(amal)
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = Bloknot()
oyna.show()
sys.exit(app.exec())
- Ob-havo tanlaş oynasini yozing: uçta
QRadioButton(Toşkent, Samarqand, Buxoro) va «Batafsil»QCheckBox. Radiotugma özgarişi bilan (toggledsignali)QLabelda tanlangan şahar va (katakça belgilangan bölsa) «batafsil maʼlumot» yozuvi çiqsin.
Yeçim
import sys
from PySide6.QtWidgets import (
QApplication, QCheckBox, QLabel, QRadioButton, QVBoxLayout, QWidget,
)
SHAHARLAR = {"Toşkent": "+24°", "Samarqand": "+21°", "Buxoro": "+27°"}
class ObHavo(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("Ob-havo")
joylashuv = QVBoxLayout(self)
self.radiolar: list[QRadioButton] = []
for nom in SHAHARLAR:
radio = QRadioButton(nom)
radio.toggled.connect(self.yangila)
self.radiolar.append(radio)
joylashuv.addWidget(radio)
self.batafsil = QCheckBox("Batafsil")
self.batafsil.toggled.connect(self.yangila)
self.yorliq = QLabel("Şaharni tanlang")
joylashuv.addWidget(self.batafsil)
joylashuv.addWidget(self.yorliq)
def yangila(self) -> None:
for radio in self.radiolar:
if radio.isChecked():
matn = f"{radio.text()}: {SHAHARLAR[radio.text()]}"
if self.batafsil.isChecked():
matn += "\nBatafsil maʼlumot: şamol sust, yoğingarçilik kutilmaydi"
self.yorliq.setText(matn)
if __name__ == "__main__":
app = QApplication(sys.argv)
oyna = ObHavo()
oyna.show()
sys.exit(app.exec())