Come scrivere un semplice editor di testo in pyqt5

Come scrivere un semplice editor di testo in pyqt5
Questo articolo coprirà una guida sulla creazione di un semplice editor di testo in Python3 e Pyqt5. QT5 è un insieme di librerie multipiattaforma scritte in C ++, utilizzate principalmente per la creazione di applicazioni grafiche ricche. Pyqt5 fornisce attacchi Python per l'ultima versione di QT5. Tutti i campioni di codice in questo articolo sono testati con Python 3.8.2 e pyqt5 versione 5.14.1 su Ubuntu 20.04.

Installazione di Pyqt5 in Linux

Per installare pyqt5 nell'ultima versione di Ubuntu, eseguire il comando di seguito:

$ sudo apt install python3-pyqt5

Se si utilizza qualsiasi altra distribuzione Linux, cerca il termine "Pyqt5" ​​nel gestore dei pacchetti e installalo da lì. In alternativa, è possibile installare PYQT5 da PIP Package Manager utilizzando il comando di seguito:

$ pip Installa pyqt5

Si noti che in alcune distribuzioni, potrebbe essere necessario utilizzare il comando PIP3 per installare correttamente PYQT5.

Codice completo

Sto pubblicando il codice completo in anticipo in modo da poter comprendere meglio il contesto per i singoli frammenti di codice spiegati più avanti nell'articolo. Se hai familiarità con Python e Pyqt5, puoi semplicemente fare riferimento al codice sottostante e saltare la spiegazione.

#!/usr/bin/env python3
Import sys
da pyqt5.QtWidgets Importa Qwidget, Qapplication, QvBoxLayout, Qhboxlayout
da pyqt5.QtWidgets Import QtextEdit, Qlabel, QShortCut, QFileDialog, QMessageBox
da pyqt5.QTGUI Import Qkey Sequence
da pyqt5 import qt
Finestra di classe (Qwidget):
def __init __ (self):
super().__dentro__()
se stesso.file_path = nessuno
se stesso.open_new_file_shortcut = qshortCut (Qkey sequence ('ctrl+o'), self)
se stesso.open_new_file_shortcut.attivato.Connetti (Self.open_new_file)
se stesso.Save_Current_file_ShortCut = QShortCut (Qkey Sequence ('Ctrl+S'), self)
se stesso.Save_Current_File_ShortCut.attivato.Connetti (Self.salve_current_file)
vbox = qvBoxLayout ()
text = "File senza titolo"
se stesso.title = qlabel (testo)
se stesso.titolo.setWordWrap (true)
se stesso.titolo.SetaLignment (Qt.Qt.Allinea al centro)
vbox.AddWidget (sé.titolo)
se stesso.SetLayout (VBox)
se stesso.scrollable_text_area = qtextEdit ()
vbox.AddWidget (sé.scrollable_text_area)
def open_new_file (self):
se stesso.file_path, filter_type = qfiledialog.getopenfilename (self, "apri nuovo file",
"", "Tutti i files (*)")
se sé.percorso del file:
Con Open (Self.file_path, "r") come f:
file_contents = f.Leggere()
se stesso.titolo.setText (self.percorso del file)
se stesso.scrollable_text_area.setText (file_contents)
altro:
se stesso.Invalid_path_alert_message ()
def save_current_file (self):
se non se stessi.percorso del file:
new_file_path, filter_type = qfiledialog.getSaveFileName (Self ", salva questo file
come ... "," "," tutti i file (*) ")
Se new_file_path:
se stesso.file_path = new_file_path
altro:
se stesso.Invalid_path_alert_message ()
restituire false
file_contents = self.scrollable_text_area.topLainText ()
Con Open (Self.file_path, "w") come f:
F.Scrivi (file_contents)
se stesso.titolo.setText (self.percorso del file)
def closeEvent (self, evento):
MessageBox = QMessageBox ()
title = "ESCIPA?"
messaggio = "Avviso !!\ n \ nif si smettono senza salvare, eventuali modifiche al file
saranno persi.\ n \ nsave prima di smettere?"
Rispondi = MessageBox.Domanda (sé, titolo, messaggio, cassetta dei messaggi.Sì | casella dei messaggi.No |
casella dei messaggi.Annulla, MessageBox.Annulla)
Se rispondi == MessageBox.SÌ:
return_value = self.save_current_file ()
se return_value == false:
evento.ignorare()
elif Rispondi == MessageBox.NO:
evento.accettare()
altro:
evento.ignorare()
def nonlid_path_alert_message (self):
MessageBox = QMessageBox ()
casella dei messaggi.setWindowTitle ("File non valido")
casella dei messaggi.setText ("Il nome file o il percorso selezionato non è valido. Seleziona a
file valido.")
casella dei messaggi.Exec ()
Se __Name__ == '__main__':
app = Qapplication (sys.argv)
w = finestra ()
w.showmaximized ()
sys.uscita (app.Exec_ ())

Spiegazione

La prima parte del codice importa solo moduli che verranno utilizzati in tutto il campione:

Import sys
da pyqt5.QtWidgets Importa Qwidget, Qapplication, QvBoxLayout, Qhboxlayout
da pyqt5.QtWidgets Import QtextEdit, Qlabel, QShortCut, QFileDialog, QMessageBox
da pyqt5.QTGUI Import Qkey Sequence
da pyqt5 import qt

Nella parte successiva, viene creata una nuova classe chiamata "Window" che eredita dalla classe "Qwidget". La classe Qwidget fornisce componenti grafici comunemente usati in QT. Usando "super" puoi assicurarti che l'oggetto QT genitore venga restituito.

Finestra di classe (Qwidget):
def __init __ (self):
super().__dentro__()

Alcune variabili sono definite nella parte successiva. Il percorso del file è impostato su "nessuno" per impostazione predefinita e scorciatoie per l'apertura di un file utilizzando e salvare un file utilizzando sono definiti utilizzando la classe QshortCut. Questi collegamenti sono quindi collegati ai rispettivi metodi che vengono chiamati ogni volta che un utente preme le combinazioni di tasti definiti.

se stesso.file_path = nessuno
se stesso.open_new_file_shortcut = qshortCut (Qkey sequence ('ctrl+o'), self)
se stesso.open_new_file_shortcut.attivato.Connetti (Self.open_new_file)
se stesso.Save_Current_file_ShortCut = QShortCut (Qkey Sequence ('Ctrl+S'), self)
se stesso.Save_Current_File_ShortCut.attivato.Connetti (Self.salve_current_file)

Utilizzando la classe QVBoxLayout, viene creato un nuovo layout su cui verranno aggiunti i widget di figli. Un'etichetta allineata al centro è impostata per il nome del file predefinito utilizzando la classe Qlabel.

vbox = qvBoxLayout ()
text = "File senza titolo"
se stesso.title = qlabel (testo)
se stesso.titolo.setWordWrap (true)
se stesso.titolo.SetaLignment (Qt.Qt.Allinea al centro)
vbox.AddWidget (sé.titolo)
se stesso.SetLayout (VBox)

Successivamente, un'area di testo viene aggiunta al layout utilizzando un oggetto QtextEdit. Il widget QTextEdit ti darà un'area modificabile e scorrevole con cui lavorare. Questo widget supporta la copia, la pasta, il taglio, il taglio, la ripetizione, il selezionare, se selezionano, tutto ecc. tasti rapidi. È inoltre possibile utilizzare un menu contestuale di clic destro all'interno dell'area di testo.

se stesso.scrollable_text_area = qtextEdit ()
vbox.AddWidget (sé.scrollable_text_area)

Il metodo "Open_new_fie" viene chiamato quando un utente completa la scorciatoia da tastiera. La classe QfileDialog presenta una finestra di dialogo. Il percorso del file viene determinato dopo che un utente seleziona un file dal selettore. Se il percorso del file è valido, il contenuto di testo viene letto dal file e impostato su widget QtextEdit. Ciò rende visibile il testo all'utente, modifica il titolo in nuovo nome file e completa il processo di apertura di un nuovo file. Se per qualche motivo, il percorso del file non può essere determinato, una casella di avviso "File non valida" viene mostrata all'utente.

def open_new_file (self):
se stesso.file_path, filter_type = qfiledialog.getopenfilename (self, "apri nuovo file", "",
"Tutti i files (*)")
se sé.percorso del file:
Con Open (Self.file_path, "r") come f:
file_contents = f.Leggere()
se stesso.titolo.setText (self.percorso del file)
se stesso.scrollable_text_area.setText (file_contents)
altro:
se stesso.Invalid_path_alert_message ()

Il metodo "Save_Current_file" viene chiamato ogni volta che un utente completa la scorciatoia da tastiera. Invece di recuperare un nuovo percorso di file, QfileDialog ora chiede all'utente di fornire un percorso. Se il percorso del file è valido, i contenuti visibili nel widget QtextEdit sono scritti sul percorso completo del file, altrimenti viene visualizzata una casella di avviso "File non valida". Il titolo del file attualmente in fase di modifica viene anche modificato nella nuova posizione fornita dall'utente.

def save_current_file (self):
se non se stessi.percorso del file:
new_file_path, filter_type = qfiledialog.getSaveFileName (Self ", salva questo file
come ... "," "," tutti i file (*) ")
Se new_file_path:
se stesso.file_path = new_file_path
altro:
se stesso.Invalid_path_alert_message ()
restituire false
file_contents = self.scrollable_text_area.topLainText ()
Con Open (Self.file_path, "w") come f:
F.Scrivi (file_contents)
se stesso.titolo.setText (self.percorso del file)

Il metodo "CloseEvent" fa parte dell'API di gestione degli eventi PYQT5. Questo metodo viene chiamato ogni volta che un utente cerca di chiudere una finestra usando il pulsante Cross o premendo la combinazione di chiavi. Al momento del fuoco dell'evento Close, all'utente viene mostrata una finestra di dialogo con tre scelte: "Sì", "No" e "Annulla". Il pulsante "Sì" salva il file e chiude l'applicazione mentre il pulsante "No" chiude il file senza salvare il contenuto. Il pulsante "Annulla" chiude la finestra di dialogo e riporta l'utente all'applicazione.

def closeEvent (self, evento):
MessageBox = QMessageBox ()
title = "ESCIPA?"
messaggio = "Avviso !!\ n \ nif si smettono senza salvare, eventuali modifiche apportate al file lo faranno
essere perso.\ n \ nsave prima di smettere?"
Rispondi = MessageBox.Domanda (sé, titolo, messaggio, cassetta dei messaggi.Sì | casella dei messaggi.No |
casella dei messaggi.Annulla, MessageBox.Annulla)
Se rispondi == MessageBox.SÌ:
return_value = self.save_current_file ()
se return_value == false:
evento.ignorare()
elif Rispondi == MessageBox.NO:
evento.accettare()
altro:
evento.ignorare()

La casella di avviso "File non valida" non ha campane e fischietti. Trasmette solo il messaggio che il percorso del file non può essere determinato.

def nonlid_path_alert_message (self):
MessageBox = QMessageBox ()
casella dei messaggi.setWindowTitle ("File non valido")
casella dei messaggi.setText ("Il nome file o il percorso selezionato non è valido. Seleziona un file valido.")
casella dei messaggi.Exec ()

Infine, il principale ciclo dell'applicazione per la gestione e il disegno degli eventi di widget viene avviato utilizzando il “.Metodo Exec_ () ".

Se __Name__ == '__main__':
app = Qapplication (sys.argv)
w = finestra ()
w.showmaximized ()
sys.uscita (app.Exec_ ())

Esecuzione dell'app

Basta salvare il codice completo su un file di testo, impostare l'estensione del file su ".py ”, contrassegna l'eseguibile del file ed eseguilo per avviare l'app. Ad esempio, se il nome del file è "Simple_text_Editor.Py ”, devi eseguire seguenti due comandi:

$ chmod +x semplice_text_editor.Py
$ ./semplice_text_editor.Py

Cose che puoi fare per migliorare il codice

Il codice spiegato sopra funziona bene per un editor di testo a ossa nudo. Tuttavia, potrebbe non essere utile per scopi pratici in quanto manca di molte caratteristiche comunemente viste in buoni redattori di testo. È possibile migliorare il codice aggiungendo nuove funzionalità come numeri di riga, evidenziazione della linea, evidenziazione della sintassi, schede multiple, salvataggio di sessioni, barra degli strumenti, menu a discesa, rilevamento delle modifiche al buffer ecc.

Conclusione

Questo articolo si concentra principalmente sulla fornitura di un terreno iniziale per la creazione di app PYQT. Se trovi errori nel codice o vuoi suggerire qualcosa, il feedback è il benvenuto.