Welcome to the Co3deX
Hello and welcome to the Open 3D Engine CO3DEX, a blog of my Journey’s in Real-time 3D Graphics, Design Technology and Technical Art. My name is Jonny Galloway, I work for @AWSCloud & my opinions are my own.
ChatGPT + Python + PySide2
I wanted to know if I could generate scaffolding and example Python code for PySide2 work by using generative-AI like ChatGPT, the answer is YES.
Technical art is a term used to describe the intersection of art and technology. It encompasses a wide range of fields, including computer graphics, video game development, and digital media. In this post, we’ll focus on one aspect of technical art: the creation of user interfaces (UIs) using Python and PySide2/Qt, and showcase example code generated by ChatGPT.
GPT (Generative Pre-trained Transformer) is a language model developed by OpenAI that uses machine learning to generate human-like text. It is a type of generative AI, a class of artificial intelligence algorithms (AI) that can generate new content or data based on patterns learned from a training data-set. Generative AI has a wide range of potential applications, including content creation, data augmentation, and machine translation. It has the potential to automate tasks previously done by humans and create new content that would not have been possible without AI. (and apparently understands generating this code to some degree, as you will see in this post.)
Python is a popular programming language that is widely used in the tech industry due to its simplicity, readability, and versatility. It is particularly well-suited for technical art projects due to its extensive libraries and frameworks for tasks such as image processing, data visualization, and GUI development.
PySide2 is a Python binding for the Qt cross-platform application framework. It provides a comprehensive set of widgets and other tools for building modern, interactive UIs. PySide2 is easy to use, powerful, and well-documented, making it a great choice for technical art projects.
This is basically the same stack used in the Open 3D Engine Editor applications, which also comes with Python and includes the PySide2 bindings for Qt UI coding … and this type of stack, is also what happens to fuel many popular 3D Digital Content Creation apps (DCC), examples are Autodesk Maya, Adobe Substance Designer, and many others (Python is like Technical Art glue.) There is a lot of potential for shared code, this is a big win to me, a more homogeneous ecosystem stack has multiplicative advantages IMO.
Knowing how to utilize this stack is very valuable to the field of Technical Art, especially in relation to real-time 3D. It allows us to build custom tools and solutions that improve our workflows, and enhance production efficiency for our art teams.
One way that you can use generative AI to enhance your day-to-day life and automate some of your tasks is by incorporating it into your technical art projects. For example, you could use a generative AI model to automatically create UI designs or graphics based on certain parameters or constraints. This could save you time and effort in the design process, allowing you to focus on other aspects of your project.
The following code block was written by ChatGPT, as part of the prompts folded in to the generation of the pre-edited paragraphs included in portions of the text above. This code, is the example it provided me, in follow up, to tie these ideas together: TechArt, Python, PySide2,and Generative AI.
Here’s an example of how you could use PySide2 and a generative AI model to create a simple UI for a weather app.
import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton
from weather_ai_model import generate_background_image
class WeatherApp(QMainWindow):
def __init__(self):
super().__init__()
# Set the window properties
self.setWindowTitle("Weather App")
self.setGeometry(100, 100, 400, 600)
# Create the central widget and layout
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout(self.central_widget)
# Create the input field and button
self.input_field = QLineEdit(self.central_widget)
self.input_field.setPlaceholderText("Enter a city name")
self.input_button = QPushButton("Get Weather", self.central_widget)
self.input_button.clicked.connect(self.on_input_button_clicked)
input_layout = QHBoxLayout()
input_layout.addWidget(self.input_field)
input_layout.addWidget(self.input_button)
self.layout.addLayout(input_layout)
# Create the weather display
self.weather_display = QLabel(self.central_widget)
self.layout.addWidget(self.weather_display)
def on_input_button_clicked(self):
# Get the city name from the input field
city = self.input_field.text()
# Use the weather AI model to generate a background image
# for the weather conditions in the city
image =
[NOTE] This code is not complete, notice the last line! I believe it may be suggesting that this is where you implement code, to pass the city to a API, then generate an image (I’ll bet in the future it would let you know that. I bet if you asked it to, with the right prompt, it might be able to suggest a service/API and also suggest the logical code. As you will see, I have done a secondary prompt to refine a class later in theis post.)
So glad I still have a purpose here.
Even if it’s simply used to get started, or you just want an example of something basic and documentation for how that works, ChatGPT looks like it will be a seriously important and valuable tool (or ecosystem) for anyone who may want to get started in this realm of Technical Art.
Some people are afraid of the implications, but the way I see it, is this is just a time reallocation … Apply the Pareto Principle (80/20 rule): get work started faster, reduce all the scaffolding and boilerplate time; so you can put 80% of your time, into the 20% of the code that is most important.
It took me about 10 minutes of playing around to generate all the code you see in this post, it took a bit longer then that, to just write and format this post (I also used the AI to scaffold some of the snippets and paragraphs in text of this posting!)
So here is where I started this particular Journey, everything you see below was prompted and generated before I wrote this blog post. Here we go…
Prompt:
Write a python package module with a template Class for a Pyside2 GUI application
Response:
Sure! Here is an example of a Python package module with a template class for a PySide2 GUI application:
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Set the window properties
self.setWindowTitle("My GUI App")
self.setGeometry(100, 100, 800, 600)
# Create the widgets and layout
# Show the window
self.show()
def main():
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the main window
window = MainWindow()
# Run the main Qt loop
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Documentation:
This module defines a
MainWindow
class that subclassesQMainWindow
from PySide2. The__init__
method sets some basic properties of the window, such as the window title and size. You can then add widgets and layouts to the window in the__init__
method or in other methods of theMainWindow
class.The
main
function creates an instance ofQApplication
, which is necessary for any PySide2 GUI application. It then creates an instance ofMainWindow
and shows it. Finally, it runs the main Qt event loop by callingapp.exec_()
.The
if __name__ == "__main__"
block ensures that themain
function is only executed if the module is run directly, rather than imported as a module by another script.I hope this helps! Let me know if you have any questions.
Prompt:
Create a “python 3.10” module, with a Class for a calculator, using PySide2
Response:
Sure! Here is an example of a Python module with a class for a calculator using PySide2:
import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QLineEdit, QPushButton
class Calculator(QMainWindow):
def __init__(self):
super().__init__()
# Set the window properties
self.setWindowTitle("Calculator")
self.setGeometry(100, 100, 300, 400)
# Create the central widget and layout
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
self.layout = QGridLayout(self.central_widget)
# Create the display and buttons
self.display = QLineEdit(self.central_widget)
self.layout.addWidget(self.display, 0, 0, 1, 4)
self.create_buttons()
def create_buttons(self):
buttons = [
("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("+", 1, 3),
("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("-", 2, 3),
("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("*", 3, 3),
("0", 4, 0), ("=", 4, 2), ("/", 4, 3)
]
for label, row, col in buttons:
button = QPushButton(label, self.central_widget)
self.layout.addWidget(button, row, col)
def main():
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the main window
window = Calculator()
window.show()
# Run the main Qt loop
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Documentation:
This module defines a
Calculator
class that subclassesQMainWindow
from PySide2. The__init__
method sets some basic properties of the window, such as the window title and size, and creates a central widget with a grid layout. It also creates a displayQLineEdit
widget and adds it to the layout.The
create_buttons
method is used to create the buttons for the calculator. It creates a list of tuples containing the label, row, and column for each button, and then creates aQPushButton
widget for each tuple and adds it to the layout.The
main
function is similar to the one in the previous example. It creates an instance ofQApplication
, creates an instance ofCalculator
, and shows it. Finally, it runs the main Qt event loop by callingapp.exec_()
.I hope this helps! Let me know if you have any questions.
Prompt:
Modify the script above to add signals and slots to the buttons, to perform logical operation of the calculator inputs
Response:
Sure! Here is an example of the modified script with signals and slots added to the buttons to perform the logical operations of the calculator:
import sys
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QLineEdit, QPushButton
class Calculator(QMainWindow):
def __init__(self):
super().__init__()
# Set the window properties
self.setWindowTitle("Calculator")
self.setGeometry(100, 100, 300, 400)
# Create the central widget and layout
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
self.layout = QGridLayout(self.central_widget)
# Create the display and buttons
self.display = QLineEdit(self.central_widget)
self.layout.addWidget(self.display, 0, 0, 1, 4)
self.create_buttons()
def create_buttons(self):
buttons = [
("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("+", 1, 3),
("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("-", 2, 3),
("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("*", 3, 3),
("0", 4, 0), ("=", 4, 2), ("/", 4, 3)
]
for label, row, col in buttons:
button = QPushButton(label, self.central_widget)
self.layout.addWidget(button, row, col)
# Connect the button's clicked signal to the appropriate slot
if label in {"+", "-", "*", "/"}:
button.clicked.connect(self.on_operator_clicked)
elif label == "=":
button.clicked.connect(self.on_equal_clicked)
else:
button.clicked.connect(self.on_digit_clicked)
@Slot()
def on_digit_clicked(self):
# Get the label of the button that was clicked
button = self.sender()
digit = button.text()
# Append the digit to the display
self.display.setText(self.display.text() + digit)
@Slot()
def on_operator_clicked(self):
# Get the label of the button that was clicked
button = self.sender()
operator = button.text()
# Append the operator to the display
self.display.setText(self.display.text() + " " + operator + " ")
@Slot()
def on_equal_clicked(self):
# Evaluate the expression in the display and display the result
result = eval(self.display.text())
self.display.setText(str(result))
def main():
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the main window
window = Calculator()
window.show()
# Run the main Qt loop
sys.exit(app.exec_())
if __name__ == "__main__":
main()
[NOTE] The code generated above, was also not 100% complete. I had to fix main() and add some additional lines of code to get it to execute correctly. But I was able to just copy and paste those fixes from one of the other generated examples!
I do not know if the application properly performs, or that it’s feature complete or bug free. But that wasn’t the point for this experiment …
import logging as _logging
_PKGNAME = 'co3dex'
_LOGGER = _logging.getLogger(_PKGNAME)
_LOGGER.info(f'Initializing: {_PKGNAME} ... Welcome to AI!')
Disclaimer: I work for @AWSCloud & my opinions are my own. Views expressed are my own. The opinions expressed here belong solely to myself, and do not reflect the views of my employer AWS, the Open 3D Foundation (or their parent the Linux Foundation.) If you are a reporter, or news outlet, please contact AWS PR (I will not reply to requests for information, they will be forwarded to my PR representative.)
License: For terms please see the LICENSE*.TXT file at the root of this distribution.
// Copyright HogJonny-AMZN. or his affiliates. All Rights Reserved.
// SPDX-License-Identifier: CC-BY-4.0