Python wird mit der Popularität von AI (Deep Learning) immer beliebter. Ich habe GUI-Anwendungen zum Anzeigen, Zeichnen und Speichern von Bildern mit Python erstellt, aber ich habe versucht, den Code zu organisieren und so weiter. Ich werde den Mechanismus schreiben, um mein Verständnis zu organisieren. Ich habe eine Bibliothek namens Qt für Python (PySide2) verwendet. Qt wurde ursprünglich in C ++ entwickelt und ermöglicht es Ihnen, plattformübergreifende Anwendungen zu entwickeln, die auf verschiedenen Betriebssystemen wie Windows, Mac und Linux aus demselben Quellcode ausgeführt werden. Es gibt Qt für Python oder PyQt, um Qt aus Python zu verwenden, aber ich habe Qt für Python verwendet, das nicht so stark an die Lizenz der erstellten App gebunden ist. Es ist leicht zu verstehen, ob Sie die Objektorientierung beim Erstellen von GUI-Anwendungen verstehen. Beim Zeichnen eines Bildes erscheinen viele Objekte, und für Anfänger ist es schwierig, die Rollen und Beziehungen der einzelnen Objekte zu verstehen. Es ist jedoch einfacher zu verstehen, ob etwas erstellt wird, das sich bewegt, auch wenn es nicht in einer schönen Form vorliegt. (Geschichte erleben) Wenn Sie also ein Bild haben, das Sie erstellen möchten, geben Sie nicht auf und probieren Sie verschiedene Dinge aus. Ich hoffe, dieser Artikel wird Ihnen zu diesem Zeitpunkt helfen.
Das Gesamtbild der App ist wie folgt. Die Bildschirmkonfiguration wird von derjenigen verwaltet, die über eine Funktion namens Layout verfügt, die die platzierten Teile (Widgets) automatisch entsprechend der Größe des Fensters anordnet.
QVBoxLayout () wird vertikal und QHBoxLayout () horizontal ausgerichtet. Verwenden Sie QFormLayout (), wenn Sie ein Paar wie einen Namen und seinen Wert erstellen möchten. Das Verwendungsbeispiel lautet wie folgt.
self.main_layout = QVBoxLayout()
#Stellen Sie den Bildanzeigebereich ein
self.graphics_view = QGraphicsView()
self.upper_layout.addWidget(self.graphics_view)
#Verschachteln Sie das Layout oben auf dem Bildschirm in das Hauptlayout
self.upper_layout = QHBoxLayout()
self.main_layout.addLayout(self.upper_layout)
Erstellen Sie eine Klasse MainWindow (QMainWIndow), die QMainWindow als Hauptfenster erbt. Platzieren Sie Teile (Widgets) mit verschiedenen Funktionen darin und beschreiben Sie den Vorgang, wenn Sie darauf drücken. Ich musste self.mainWidget = QWidget (self) in der Initialisierung hier deklarieren, bevor ich Layout festlegen konnte.
Der Code zum Starten der Anwendung sieht folgendermaßen aus:
class MainWindow(QMainWindow):
def __init__(self):
#Nachfolgend werden verschiedene Prozesse beschrieben
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Deklarieren Sie es im Konstruktor (def init ()), um im Hauptfenster eine Menüleiste (Auswahl oben in der Anwendung) zu erstellen. Gehen Sie wie folgt vor, um eine Menüleiste und ein Menü mit dem Namen "Datei" zu erstellen.
class MainWindow(QMainWindow):
def __init__(self):
self.main_menu = self.menuBar()
self.file_menu = self.main_menu.addMenu('File')
Wenn Sie im Menü "Datei" ein Element mit dem Namen "Datei öffnen" erstellen möchten, gehen Sie wie folgt vor.
# Set "Original Image Open" menu
self.org_img_open_button = QAction(self.style().standardIcon(getattr(QStyle, 'SP_FileDialogStart')), 'Open Orginal Image', self)
self.org_img_open_button.setShortcut('Ctrl+O')
self.org_img_open_button.triggered.connect(self.open_org_img_dialog)
self.file_menu.addAction(self.org_img_open_button)
In der ersten Zeile wird QAction () festgelegt, das funktioniert, wenn dieses Element ausgewählt wird, das Symbol aus den Standardelementen ausgewählt wird und der angezeigte Name "Open Orginal Image" lautet. Die zweite Zeile ist so eingestellt, dass dieses Element mit der Tastenkombination Strg + O ausgewählt werden kann. Die dritte Zeile ist mit der Funktion verbunden, die das Verhalten bei Auswahl dieses Elements festlegt. Dies wird im nächsten Abschnitt erläutert. Dieser Artikel ist in file_menu in der 4. Zeile registriert.
Bei Qt werden Benutzeroperationen und entsprechende Computerreaktionen mit Methoden ausgeführt, die als Signal und Slot bezeichnet werden. Das Signal wird ausgegeben, wenn der Benutzer eine Operation wie eine Menütaste oder das Ziehen der Maus ausführt. Führen Sie dann die entsprechende Verarbeitung in dem definierten Steckplatz durch, um jedes Signal zu empfangen. Insbesondere wird die Operation, wenn ein Element in der Menüleiste ausgewählt ist, wie folgt geschrieben.
#Menüleiste->Datei-> 'Original Image Open'Wann ist ausgewählt
#Senden Sie ein ausgelöstes Signal. Das Signal ist offen_org_img_Verbunden mit der Dialogfunktion.
self.org_img_open_button = QAction(self.style().standardIcon(getattr(QStyle, 'SP_FileDialogStart')), 'Open Orginal Image', self)
self.org_img_open_button.triggered.connect(self.open_org_img_dialog)
#Menüleiste->Datei-> 'Original Image Open'Eine Funktion, die zu einem Steckplatz wird, der das bei der Übertragung gesendete Signal empfängt
def open_org_img_dialog(self):
options = QFileDialog.Options()
org_img_default_path = self.app_setting["SoftwareSetting"]["file_path"]["org_img_dir"]
self.org_img_file_path, selected_filter = QFileDialog.getOpenFileName(self, 'Select original image', org_img_default_path, 'Image files(*.jpg *jpeg *.png)', options=options)
org_img_dir_path, org_img_file = os.path.split(self.org_img_file_path)
org_img_bare_name, org_img_ext = os.path.splitext(org_img_file)
self.org_img_path_label.setText(self.org_img_file_path)
Wenn eine Farbe durch Klicken mit der Maus in der später beschriebenen Farbleiste ausgewählt wird, wird die ausgewählte Farbe als Quadrat im Zeichenbereich zur Anzeige gezeichnet, um dem Benutzer das Verständnis zu erleichtern. Zu diesem Zeitpunkt muss zwischen dem Farbbalken und dem Objekt im ausgewählten Farbzeichnungsbereich gearbeitet werden. Zu diesem Zeitpunkt ist es erforderlich, Signal und Steckplatz über das übergeordnete Hauptfenster zu verbinden. In diesem Fall definiert die Klasse, die die Zeichnungselemente verwaltet, die im ausgewählten Farbzeichnungsbereich platziert werden sollen, ihr eigenes Signal und sendet das Signal mit den Farbinformationen des angeklickten Teils. Insbesondere sieht der Code wie folgt aus.
# Class for graphics contents of tools on main window
class GraphicsSceneForTools(QGraphicsScene):
# Define custom signal
img_info = Signal(QColor)
def mousePressEvent(self, event):
# For check program action
pos = event.scenePos()
x = pos.x()
y = pos.y()
#Wenn der Cursor oder Stift in der Bildbearbeitungssymbolleiste ausgewählt ist, werden die Farbinformationen der angeklickten Stelle angezeigt(QColor)Geben Sie ein Signal mit aus
if self.mode == 'cursor' or self.mode == 'pen':
self.pix_rgb = self.img_content.pixelColor(x, y)
self.img_info.emit(self.pix_rgb)
#Definieren Sie den Steckplatz, der dem Signal der auf der Seite des Hauptfensters ausgewählten Farbinformationen entspricht
class MainWindow(QMainWindow):
#Verwaltungsobjekt für Zeichnungselemente für Farbbalken
self.color_bar_scene = GraphicsSceneForTools()
#Stellen Sie eine Verbindung mit einer Funktion her, die zu einem Steckplatz wird, der das Signal empfängt, das die Farbinformationen gesendet hat
self.color_bar_scene.img_info.connect(self.set_selected_color)
Für die Bildanzeige sind mehrere Widgets verknüpft. Die Beziehung ist wie in der folgenden Abbildung dargestellt. Bereiten Sie QGraphicsView, ein Zeichenbereichsobjekt, in MainWindow vor, platzieren Sie QGraphicsScene, das Zeichnungsobjekte enthält und verwaltet, und fügen Sie Zeichnungen und Bilder wie Linien und Kreise zu QGraphicsScene hinzu. Gehen.
Die im Hauptzeichnungsbereich festgelegte QGraphicsScene zeigt die Pixelinformationen des angezeigten Bildes in der Statusleiste an, wenn das Cursorwerkzeug ausgewählt ist, und die Ebene über dem Bild, wenn das Stift- oder Radiergummiwerkzeug ausgewählt ist. Ich werde versuchen zu zeichnen. Um einen solchen Funktionssatz selbst hinzuzufügen, erstellen Sie eine Grafikszene, die die QGraphic-Szene wie folgt erbt. Durch Festlegen des übergeordneten Zeichenbereichs QGraphicsView und seines übergeordneten Hauptfensters in der Initialisierungsinitialisierungsfunktion können die von jedem Element dieser GraphicsScene erhaltenen Informationen an den Zeichenbereich oder das Fenster übergeben werden.
Um ehrlich zu sein, bin ich mir bei QGraphicsView und QGraphicsScene zunächst nicht sicher, aber ich fand es kompliziert und mühsam, auf die Inhalte zuzugreifen und sie zu kontrollieren! Dies scheint darauf zurückzuführen zu sein, dass es die komplizierte Anforderung des Zeichnens innerhalb des sichtbaren Bereichs (Zeichenbereich) aus verschiedenen Blickwinkeln erfüllt, auch wenn sich der zu zeichnende Zielinhalt nicht ändert. Wenn der zu zeichnende Inhalt beispielsweise größer als der Zeichenbereich ist, wird er möglicherweise angezeigt, während der Ansichtspunkt mit der Bildlaufleiste geändert wird, oder ein 3D-Objekt wird angezeigt, während der Ansichtspunkt geändert wird.
class GraphicsSceneForMainView(QGraphicsScene):
def __init__(self, parent=None, window=None, mode='cursor'):
QGraphicsScene.__init__(self, parent)
# Set parent view area
self.parent = parent
# Set grand parent window
self.window = window
# Set action mode
self.mode = mode
# mouse move pixels
self.points = []
# added line items
self.line_items = []
self.lines = []
# added line's pen attribute
self.pens = []
def set_mode(self, mode):
self.mode = mode
def set_img_contents(self, img_contents):
# image data of Graphics Scene's contents
self.img_contents = img_contents
def clear_contents(self):
self.points.clear()
self.line_items.clear()
self.lines.clear()
self.pens.clear()
self.img_contents = None
def mousePressEvent(self, event):
# For check program action
pos = event.scenePos()
x = pos.x()
y = pos.y()
if self.mode == 'cursor':
# Get items on cursor
message = '(x, y)=({x}, {y}) '.format(x=int(x), y=int(y))
for img in self.img_contents:
# Get pixel value
pix_val = img.pixel(x, y)
pix_rgb = QColor(pix_val).getRgb()
message += '(R, G, B) = {RGB} '.format(RGB=pix_rgb[:3])
# show scene status on parent's widgets status bar
self.window.statusBar().showMessage(message)
Link zur QGraphicsView-Dokumentation Link zur QGraphicsScene-Dokumentation
Verwenden Sie QGraphicsScene.addItem (QPixmap) im Format QPixmap, um ein Bild in QGraphicsScene zu platzieren. Im QPixmap-Format können die Informationen der einzelnen Pixel jedoch nicht erfasst oder neu geschrieben werden. Behalten Sie sie daher im QImage-Format bei und konvertieren Sie sie zum Zeichnen in QPixmap. Um ein QImage aus einer Bilddatei zu erstellen, verwandeln Sie es in eine QPixmap und fügen Sie es der QGraphicsScene hinzu. Der Code sieht folgendermaßen aus:
#self bezieht sich auf MainWindow
self.scene = GraphicsSceneForMainView(self.graphics_view, self)
self.org_qimg = QImage(self.org_img_file_path)
self.org_pixmap = QPixmap.fromImage(self.org_qimg)
scene.addItem(self.org_pixmap)
Verwenden Sie den folgenden Code, um ein QImage von 8 Bit (256 Abstufungen) RGBA (A ist Transparenz) am Himmel zu erstellen.
self.layer_qimg = QImage(self.org_img_width, self.org_img_height, QImage.Format_RGBA8888)
Link zur QImage-Dokumentation Link zur QPixmap-Dokumentation
Dieser Artikel wird als Referenz verwendet, und die Farbleiste zur Auswahl der Stiftfarbe wird einer Wärmezuordnung zugeordnet (glatt von Blau bei niedriger Temperatur bis Rot bei hoher Temperatur). Ich habe es geschafft mit (ändern). Das Objekt, mit dem die Farbleiste festgelegt wird, ist teilweise in der Erläuterung von "Mechanismus zum Empfangen von Aktionen für Teile" beschrieben. Ich habe jedoch eine Klasse namens GraphicsSceneForTools erstellt, die QGraphicsScene geerbt und verwendet hat. Auf diese Weise wird durch Klicken mit der Maus ein Signal entsprechend der von diesem Objekt gedrückten Position und im MainWindow (genauer gesagt MainWindow-> QGraphicsView-> GraphicsSceneForTools) des übergeordneten Objekts ausgegeben, in dem sich das Objekt befindet. Durch Vorbereiten einer Slot-Funktion, die von Signal empfangen werden soll, wird der ausgewählte Farbanzeigebereich mit der vom Benutzer in der Farbleiste ausgewählten Farbe gefüllt und auf leicht verständliche Weise angezeigt. In der neu vorbereiteten Klasse GraphicsSceneForTools (QGraphicsScene) wird ein Signal mit QColor (Farbinformationen) als img_info = Signal (QColor) vorbereitet und beim Klicken der Maus in def mousePressEvent (self, event) festgelegt. Ich versuche, ein Signalsignal mit der Farbe (self.pix_rgb) der angeklickten Koordinatenposition des Zeichnungselements (in diesem Fall Farbbalken) als self.img_info.emit (self.pix_rgb) auszugeben. Auf der MainWindow-Seite wird set_selected_color () als Slot-Funktion auf der Empfangsseite vorbereitet, wenn das GraphicsSceneForTools-Objekt das entsprechende Signal als self.color_bar_scene.img_info.connect (self.set_selected_color) ausgibt. Insbesondere lautet der Code wie folgt.
class MainWindow(QMainWindow):
# Set color bar
self.color_bar_width = 64
self.color_bar_height = 256
self.color_bar_view = QGraphicsView()
self.color_bar_view.setFixedSize(self.color_bar_width+3, self.color_bar_height+3)
self.color_bar_scene = GraphicsSceneForTools()
#Stellen Sie die Farbleiste ein.
#Die Farbänderungsdaten, die der Farbleiste zugrunde liegen, sind selbst.colormap_Es ist in Daten.
#Informationen zum Erstellen finden Sie im Quellcode oder im Referenzartikel.
self.color_bar_img = QImage(self.color_bar_width, self.color_bar_height, QImage.Format_RGB888)
for i in range(self.color_bar_height):
# Set drawing pen for colormap
ii = round(i * (1000/256))
color = QColor(self.colormap_data[ii][0], self.colormap_data[ii][1], self.colormap_data[ii][2])
pen = QPen(color, 1, Qt.SolidLine, \
Qt.SquareCap, Qt.RoundJoin)
self.color_bar_scene.addLine(0, self.color_bar_height - i-1, self.color_bar_width, self.color_bar_height - i-1, pen=pen)
for j in range(self.color_bar_width):
self.color_bar_img.setPixelColor(j, self.color_bar_height-i-1, color)
self.color_bar_scene.set_img_content(self.color_bar_img)
self.color_bar_view.setScene(self.color_bar_scene)
# Connect signal to slot of color_bar_scene
self.color_bar_scene.img_info.connect(self.set_selected_color)
# Slot of color bar clicked for selection color
def set_selected_color(self, color):
# Delete existng image item
self.select_color_scene.removeItem(self.select_color_rect)
self.draw_color = color
brush = QBrush(self.draw_color)
self.select_color_rect = self.select_color_scene.addRect(QRect(0, 0, self.select_color_view_size, self.select_color_view_size), \
brush=brush)
self.select_color_view.setScene(self.select_color_scene)
# Class for graphics contents of tools on main window
class GraphicsSceneForTools(QGraphicsScene):
# Define custom signal
img_info = Signal(QColor)
def __init__(self, parent=None, window=None):
QGraphicsScene.__init__(self, parent)
# Set parent view area
self.parent = parent
# Set grand parent window
self.window = window
self.mode = 'cursor'
def set_mode(self, mode):
self.mode = mode
def set_img_content(self, img_content):
# image data of Graphics Scene's contents
self.img_content = img_content
def mousePressEvent(self, event):
# For check program action
pos = event.scenePos()
x = pos.x()
y = pos.y()
if self.mode == 'cursor' or self.mode == 'pen':
self.pix_rgb = self.img_content.pixelColor(x, y)
self.img_info.emit(self.pix_rgb)
Mit den oben genannten Inhalten können Sie einen Stift oder ein Radiergummi zum Zeichnen auswählen. Das Originalbild wird angezeigt und das Ergebnis meiner Zeichnung wird auf einer anderen Ebene darüber gezeichnet. Um den von Ihnen gezeichneten Inhalt zu speichern, müssen Sie den gezeichneten Inhalt exportieren, indem Sie die Maus als Bild ziehen. Der durch Ziehen mit der Maus des Benutzers gezeichnete Inhalt wird als Sammlung von Linien gespeichert, die Loci sind. Linien haben Start- und Endpunkte sowie Stiftattribute (Farbe, Größe). Daher werden die Koordinaten, die das Bild weitergeben, basierend auf dem Startpunkt und dem Endpunkt in der Reihenfolge aus der Gruppe von Linien berechnet und im Bild für den Export wiedergegeben.
#Eine Klasse, die Elemente verwaltet, die im Zeichenbereich platziert werden sollen
class GraphicsSceneForMainView(QGraphicsScene):
#Wenn ein Stift oder Radiergummi durch Ziehen der Maus ausgewählt und gezeichnet wird
def mouseMoveEvent(self, event):
# For check program action
pos = event.scenePos()
x = pos.x()
y = pos.y()
if self.mode == 'pen' or self.mode == 'eraser':
if x >= 0 and x < self.width() and y >= 0 and y < self.height():
if len(self.points) != 0:
draw_color = self.window.draw_color
# Set transparenc value
draw_color.setAlpha(self.window.layer_alpha)
draw_size = self.window.draw_tool_size
pen = QPen(draw_color, draw_size, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
self.lines_items.append(self.addLine(QLineF(self.points[-1].x(), self.points[-1].y(), x, y), pen=pen))
#Die Position der gezeichneten Linie und die Attribute des Stifts zu diesem Zeitpunkt zum späteren Speichern als Bild(Farbe, Größe)sparen
self.lines.append(self.lines_items[-1].line())
self.pens.append(pen)
self.points.append(pos)
# Main Window components
class MainWindow(QMainWindow):
#Verarbeitung, um die Zeichnung des Benutzers auf dem Bild wiederzugeben
#Der durch Ziehen der Maus gezeichnete Inhalt ist eine Sammlung von Linieninformationen mit einem Startpunkt und einem Endpunkt.
def make_layer_image(self):
for i, line in enumerate(self.scene.lines):
pen = self.scene.pens[i]
pen_size = int(pen.width())
pen_color = pen.color()
# start pixel of line
x1 = int(line.x1())
y1 = int(line.y1())
# end pixel of line
x2 = int(line.x2())
y2 = int(line.y2())
dx = int(line.dx())
dy = int(line.dy())
# When only 1pixl line
if dx <= 1 and dy <= 1:
draw_pix_x1_s = max(x1 - int(pen_size/2), 0)
draw_pix_x1_e = min(x1 + int(pen_size/2), self.org_img_width-1)
draw_pix_y1_s = max(y1 - int(pen_size/2), 0)
draw_pix_y1_e = min(y1 + int(pen_size/2), self.org_img_height-1)
# for Pen's size
for y in range(draw_pix_y1_s, draw_pix_y1_e):
for x in range(draw_pix_x1_s, draw_pix_x1_e):
self.layer_qimg.setPixelColor(x, y, pen_color)
draw_pix_x2_s = max(x2 - int(pen_size/2), 0)
draw_pix_x2_e = min(x2 + int(pen_size/2), self.org_img_width-1)
draw_pix_y2_s = max(y2 - int(pen_size/2), 0)
draw_pix_y2_e = min(y2 + int(pen_size/2), self.org_img_height-1)
# for Pen's size
for y in range(draw_pix_y2_s, draw_pix_y2_e):
for x in range(draw_pix_x2_s, draw_pix_x2_e):
self.layer_qimg.setPixelColor(x, y, pen_color)
else:
# For avoid devide by 0
if dx == 0:
for y in range(y1, y2+1):
draw_pix_y_s = y - int(pen_size/2)
draw_pix_y_e = y + int(pen_size/2)
# for Pen's size
for yy in range(draw_pix_y_s, draw_pix_y_e):
self.layer_qimg.setPixelColor(x1, yy, pen_color)
else:
grad = dy/dx
# Choose coordinates with small slope not to skip pixels
if grad >= 1.0:
for x in range(dx):
y = y1 + int(grad * x + 0.5)
draw_pix_x_s = max(x1 + x - int(pen_size/2), 0)
draw_pix_x_e = min(x1 + x + int(pen_size/2), self.org_img_width-1)
draw_pix_y_s = max(y - int(pen_size/2), 0)
draw_pix_y_e = min(y + int(pen_size/2), self.org_img_height-1)
# for Pen's size
for yy in range(draw_pix_y_s, draw_pix_y_e+1):
for xx in range(draw_pix_x_s, draw_pix_x_e+1):
self.layer_qimg.setPixelColor(xx, yy, pen_color)
else:
for y in range(dy):
x = x1 + int(1/grad * y + 0.5)
draw_pix_y_s = max(y1 + y - int(pen_size/2), 0)
draw_pix_y_e = min(y1 + y + int(pen_size/2), self.org_img_height-1)
draw_pix_x_s = max(x - int(pen_size/2), 0)
draw_pix_x_e = min(x + int(pen_size/2), self.org_img_width-1)
# for Pen's size
for yy in range(draw_pix_y_s, draw_pix_y_e+1):
for xx in range(draw_pix_x_s, draw_pix_x_e+1):
self.layer_qimg.setPixelColor(xx, yy, pen_color)
Fügen Sie dem Menü "Datei" "Ebenenbild speichern" hinzu. Wenn Sie es auswählen, wird das vom Benutzer gezeichnete Bild gespeichert. Im Einzelnen lautet der Code wie folgt: Führen Sie den Vorgang zum Erstellen eines QImage-Bilds aus, das die Zeichnung mit make_layer_image () widerspiegelt, öffnen Sie den Dateidialog zum Speichern und speichern Sie mit dem eingegebenen Bilddateinamen. Machen.
# Main Window components
class MainWindow(QMainWindow):
def __init__(self):
# Set "Save layer image" menu
self.layer_img_save_button = QAction(self.style().standardIcon(getattr(QStyle, 'SP_FileDialogEnd')), 'Save Layer Image', self)
self.layer_img_save_button.setShortcut('Ctrl+S')
self.layer_img_save_button.triggered.connect(self.save_layer_image)
self.file_menu.addAction(self.layer_img_save_button)
# Slot function of save layer image button clicked
def save_layer_image(self):
self.make_layer_image()
layer_img_default_path = self.app_setting["SoftwareSetting"]["file_path"]["layer_img_dir"]
options = QFileDialog.Options()
file_name, selected_filete = QFileDialog.getSaveFileName(self, 'Save layer image', layer_img_default_path, \
'image files(*.png, *jpg)', options=options)
self.layer_qimg.save(file_name)
ret = QMessageBox(self, 'Success', 'layer image is saved successfully', QMessageBox.Ok)
Qt wird außerdem mit einem Tool namens Qt Designer geliefert, das Teile wie Schaltflächen auf dem Bildschirm der Anwendung anordnet, die Sie auf dem GUI-Bildschirm erstellen möchten. Bevor Sie sich daran gewöhnen, können Sie sich leicht vorstellen, welche Art von Teilen (Widget) Sie haben. Daher ist es möglicherweise einfacher zu verstehen, wenn Sie versuchen, damit ein Erscheinungsbild zu erstellen.
Der Quellcode der erstellten Anwendung wird an der folgenden Stelle veröffentlicht. App-Quellcodepage
Recommended Posts