QLineEdit’e tıklanma durumunu kontrol edecek bir fonksiyon var mı ? Clicked fonksiyonunu aradım ancak QLineEdit’lerin böyle bir fonksiyonu yok anlaşılan.
Bir XOX oyunu projem var. Kutucuklara harfleri yazarak oynuyorduk ve kodların tamamını sıfırlayıp baştan yazmaya karar verdim. Artık kutucuklara (lineEditlere) tıklanarak harf koyulacak.
Olur da böyle bir şey bulamazsak kutucukların üzerine gizli bir buton yerleştirir öyle yaparım.
bu linki bulmuştum araştırma yaparken. Ancak anlayamadım. Bir de siz bakın derim
Mouse ile pencere üzerinde herhangi bir yere tıklandığında mousePressEvent fonksiyonuna bir QMouseEvent nesnesi gönderiliyor. Bu nesnenin, içerisinde hangi bilgileri içerdiğine şuradan bakabilirsiniz.
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import ttt_ui
import sys
import random
class window(QMainWindow,ttt_ui.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.msgbox = QMessageBox
self.timer = QTimer
self.bot_right_block = self.bot_left_block_2
self.player1_score = "0"
self.player2_score = "0"
self.label_4.setText(self.player1_score)
self.label_6.setText(self.player2_score)
# table
self.table = [
[self.left_top_block, self.top_middle_block, self.top_right_block], # row 1
[self.middle_left_block, self.middle_middle_block, self.middle_right_block], # row 2
[self.bot_left_block, self.bot_middle_block, self.bot_right_block] # row 3
]
# setting "setReadOnly" function to whole table and appending elements to our list to use them for "mouseReleaseEvent"
self.mouseReleaseEvent_list = list()
for i in self.table:
for l in i:
l.setReadOnly(True)
self.mouseReleaseEvent_list.append(l)
# Iterations to connecting table elements to "mouseReleaseEvent" functions
iteration = iter(self.mouseReleaseEvent_list)
element_1 = next(iteration)
element_1_connection = element_1.mouseReleaseEvent = self.MRE_function1
element_2 = next(iteration)
element_2_connection = element_2.mouseReleaseEvent = self.MRE_function2
element_3 = next(iteration)
element_3_connection = element_3.mouseReleaseEvent = self.MRE_function3
element_4 = next(iteration)
element_4_connection = element_4.mouseReleaseEvent = self.MRE_function4
element_5 = next(iteration)
element_5_connection = element_5.mouseReleaseEvent = self.MRE_function5
element_6 = next(iteration)
element_6_connection = element_6.mouseReleaseEvent = self.MRE_function6
element_7 = next(iteration)
element_7_connection = element_7.mouseReleaseEvent = self.MRE_function7
element_8 = next(iteration)
element_8_connection = element_8.mouseReleaseEvent = self.MRE_function8
element_9 = next(iteration)
element_9_connection = element_9.mouseReleaseEvent = self.MRE_function9
# MRE = mouseReleaseEvent
def MRE_function1(self, event):
print("num1 has worked")
def MRE_function2(self, event):
print("num2 has worked")
def MRE_function3(self, event):
print("num3 has worked")
def MRE_function4(self, event):
print("num4 has worked")
def MRE_function5(self, event):
print("num5 has worked")
def MRE_function6(self, event):
print("num6 has worked")
def MRE_function7(self, event):
print("num7 has workeds")
def MRE_function8(self, event):
print("num8 has worked")
def MRE_function9(self, event):
print("num9 has worked")
app = QApplication(sys.argv)
pencere = window()
pencere.setWindowTitle("Tic Tac Toe")
pencere.setWindowIcon(QIcon("indir.png"))
pencere.show()
sys.exit(app.exec_())
Bir soru daha soracağım. Yeni bir konu açmak yerine buradan tekrar size yazmak istedim, doğru mu yaptım bilmiyorum ancak basit bir konu olduğu için buradan tekrar size yazmayı tercih ettim.
Projeye ufaktan başladım, yukarıdaki attığım kodlardan da göreceğiniz üzere.
Kodların Okunaklı olduğunu düşünüyor musunuz ? Ya da yorum satırları ve değişken isimleri uygun mudur ?
Bütün table öğelerine tek tek mouseReleaseEvent ekleyip bir fonksiyona bağlamak yerine Iterations kullanmayı tercih ettim. Doğru bir tercih midir ?
yani şunu mu yapmak daha kısa ve okunaklı olurdu ? :
Skorlar integer tipinde olsa iyi olur, rahatlıkla artırabilmeniz için. Display ederken string'e dönüştürmeniz yeterli.
Bunlar lineEdit’ler mi? Eğer öyle ise şurası hata vermeli:
Çünkü QLineEdit nesneleri iterable değiller.
Bu kısımda basit bir for döngüsünü elle yazmışsınız.
Bu kadar fonksiyona gerek yok. Sadece bir tane kontrol mekanizması olması yeterli, ki daha okunaklı bir kod olmasını da sağlar.
Değişken isimleri iyi, yalnızca self.table'ın ismini self.blocks olarak değiştirin. Çünkü liste içerisinde çok fazla block kelimesi kullanılmış. Yorum satırları iyi.
Tüm QLineEdit'leri bir fonksiyona bağlamak bir çok açıdan daha doğru olur:
for lineEdit in self.table:
lineEdit.setReadOnly(True)
lineEdit.mouseReleaseEvent = self.control # hamle yapıldı
def control(self):
pass
Bunların dışında, tavsiye olarak;
Kullanacağınız algoritmayı düşünürken, projeye geniş bir çerçeveden bakın. Şimdiki durumu ve ileride yapacağınız eklemeleri düşünün. Sadece önünüzdeki probleme odaklanmayın, “bunu çözeyim de, sonrasına sonra bakarım” demeyin. Yeni bir özellik, öncesindeki ve sonrasındaki özelliklere zarar verebilir. Programın tutarsız, stabil çalışmaması ve çokca bug içermesi gayet olası.
Evet onlar lineEdit.
İterable değillerdir belki ancak sonuçta listenin içinde döndüğüm için hata vermiyordur bence.
Farkındayım çünkü tek bir for döngüsü yazmak hepsini aynı fonksiyona bağlayacaktı ancak ben öyle olmasını istemiyorum.
Dediğim gibi bir fonksiyona bağlamak istemiyorum. Bunun sebebi; eğer bir fonksiyona bağlarsam, lineEditlere tıklanma durumunu kontrol edemem.
Yani bir lineEdite tıklıyorum. Sadece tıklamış olduğum lineEdit’e X koyması lazım. Ancak hepsini tek bir fonksiyona bağlarsam olmaz çünkü tıklamış olduğum lineEdite X koyululduktan sonra diğer LineEditler de aynı fonksiyona bağlı olduğu için onlara da X koyulur.
Umarım anlatabilmişimdir
Eğer bir tane lineEdite tıklarsam, bütün tıklanma durumları bu fonksiyona bağlı olduğu için bütün tıklanma durumları aynı işlevi gerçekleştirir dolayısıyla da bütün lineEditlere “X” stringi setText edilir. Neden? Çünkü bu fonksiyonun içinde bütün lineEditlere “X” koyulması gerektiği söyleniyor ve söylenilmesi de gerekli.
ayrı ayrı fonksiyon yazmak doğru bir tercih miydi? Yoksa bahsettiğim durum değiştirilebilir mi?
If bloklarıyla kontrol edilebilir mi ?
def MRE_funct(self, event) :
if self.table[0][0].triggered:
self.table[0][0].setText("X")
.........
Yani If bloklarıyla bunun gibi bir şey yapılır mı ? Ya da dediğim gibi başka bir şekilde bahsettiğim durumu değiştirmek mümkün mü ? Ben böyle bir şeyin mümkün olup olmadığını bilmediğim için ve üzerinde herhangi bir tahmin yürütemediğim için mümkün değil varsayarak ayrı ayrı fonksiyonlara bağlamayı tercih ettim.
Anlaşılamadıysam belirtin lütfen daha daha detaylı yazarım.
Edit :
Eğer böyle bir şey mümkün değilse, yaptığım iteration’u for döngüsüyle yapmak mümkün müdür ?
Ben en baştan iteratorler kullanarak yapmaya çabaladım çünkü dediğim gibi hepsi birbirinden farklı fonksiyonlara bağlanıyorlar. Az önce belki for döngüsüyle de yapılır diyerek bir şeyler denedim.
Burada da anlaşılır olacak şekilde yazmaya çalıştım. Yukarıdaki kodları yazdığım zaman gerçekten de fonksiyona bağlanılıyor ancak hangi lineEdit’e tıklarsam tıklayayım “num9 has worked” çıktısını veriyor. Sağ alttaki bloğa denk geliyor bu da. Yani table[2][2] öğesine. Sadece table[2][2] öğesinin çalışmasını beklememiştim açıkçası
Ben şöyle düşünmüştüm, tüm lineedit’lerin sinyalini kontrol fonksiyonuna bağlarız. Ordan da ‘sıra’ hangi oyuncuda ise (x,o) ona göre kutucuğa “X” veya “O” yazacaktık. Fakat üretilen sinyal bize sadece QMouseEvent nesnesini veriyor, bu nesne üzerinden de kısıtlı bilgilere erişebiliyoruz. Hangi butonla tıklandığı, mouse pozisyonu vs.
Dolayısıyla haklısınız, hangi lineedit’e tıklandığını bilemiyoruz. Şöyle bir yöntem düşündüm, acaba tıklanan koordinattaki nesneyi alabilir miyiz? Araştırınca, bunun mümkün olduğunu öğrendim;
QMainWindow.childAt(x,y)
Return type: QWidget
Uygulamaya geçirmeye çalıştığımda, tüm QLineEdit nesnelerinin etkilendiğini gördüm, doğal olarak. Çünkü bu metod eğer verilen pozisyonda bir QWidget nesnesi var ise nesneyi döndürüyor. event’dan gelen koordinatta centralWidget (merkezi/ana widget) var. lineEdit’lerimiz de bu widget üzerinde olduğu için hepsi etkileniyor. Doğrudan QLineEdit'i vermeye kalkışsak bu kez hiçbir şey elde edemeyiz, çünkü QLineEdit bir widget değil:
Belki QLineEdit'leri ayrı ayrı QWidget nesneleri üzerine yerleştirmek problemi çözebilir ama bende onu yapacak hal kalmadı İsterseniz deneyip görün, ya da her kutucuk için ayrı fonksiyon yazın. Daha sonra, daha iyi bir fikir bulduğunuzda tekrar düzeltirsiniz.
Uğraşınız için çok teşekkür ederim. lineEdit sınıfları centralWidget’ı miras aldıkları için hepsi etkileniyor. Onları farklı widgetlara koyarak
bu kodu kullanmamı istiyorsunuz doğru anlamışım değil mi ?
Kullanıcı her zaman X’i oynayacak. O’yu ise bilgisayar oynayacaktı.
bunun dışında
şu for döngüsü kullanımım doğru olmuş mu ? Neden sadece table[2][2] öğesi çalışıyor ? Kısaca cevaplayabilir misiniz ?
13. gönderimde biraz daha detaylı yazdım burayı
Evet, centralWidget'ı tamamen kaldırın, gerek yok.
Daha az kod demek.
Hayır. for objects in objects ilginç olmuş, döngü için (her iter'i temsil eden değişken olarak) sınıf niteliği kullanımını da ilk kez görüyorum: for self.functs in MRE_Functions
Emin değilim ama döngüyü dediğim gibi düzeltirseniz, problem belki çözülebilir. Problem çözülmezse tekrar bakalım.
Evet yapıyormuş. Self’i çıkararak denedim ancak yine aynı sonucu verdi. (“num9 has worked”)
İsterseniz size ui ve main dosyasını atayım, kendiniz kurcalayarak incelersiniz. Sizi de yormak istemiyorum açıkçası. Bence ben bir süre bir şeyler deneyeyim. Hiç olmazsa size mesaj atarım olur mu ?