1

Here is the code of my program. This program is made for people to make a Gas molecule Simulation. When you press the Addmolecule button in the Ui, molecules should be displayed randomly on the Ui. However, it doesn't work. I need help....

import sys
import random
import math
from PyQt5.QtWidgets import QApplication, QMainWindow, QSlider, QLabel, QVBoxLayout, QWidget, QPushButton, QGraphicsEllipseItem, QGraphicsScene, QGraphicsView
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtCore import Qt
from PyQt5 import uic

form_ui = uic.loadUiType("qqq.ui")[0]

class GasMoleculeWindow(QMainWindow, form_ui):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
         
        self.setWindowTitle("Gas Molecule Simulation")
        self.setGeometry(100, 100, 800, 600)

        self.molecules = []
        self.temperature = 1.0

        self.addMoleculeButton.clicked.connect(self.addMolecule)
        self.stopSimulation.clicked.connect(self.stopProgram)
        self.massSlider.setRange(1,10)
        self.massSlider.valueChanged.connect(self.updateMass)
        self.radiusSlider.valueChanged.connect(self.updateRadius)
        self.temperatureSlider.valueChanged.connect(self.updateTemperature)

        self.massLabel.setAlignment(Qt.AlignCenter)
        self.radiusLabel.setAlignment(Qt.AlignCenter)
        self.temperatureLabel.setAlignment(Qt.AlignCenter)

        self.scene = QGraphicsScene(self)
        self.view = QGraphicsView(self.scene)

        layout = QVBoxLayout(self)
        layout.addWidget(self.view)

        self.timer = self.startTimer(10)

    def addMolecule(self):
        for _ in range(10):
            molecule = {
                'x': random.uniform(0, self.width()),
                'y': random.uniform(0, self.height()),
                'vx': random.uniform(-1, 1) * math.sqrt(3 * self.temperature / self.massSlider.value()),
                'vy': random.uniform(-1, 1) * math.sqrt(3 * self.temperature / self.massSlider.value()),
                'mass': self.massSlider.value(),
                'radius': self.radiusSlider.value()
            }
            self.molecules.append(molecule)

            molecule_item = QGraphicsEllipseItem(
                molecule['x'] - molecule['radius'],
                molecule['y'] - molecule['radius'],
                2 * molecule['radius'],
                2 * molecule['radius']
            )
            molecule_item.setBrush(QColor(255, 0, 0))

            mass_color = self.getColorByMass(molecule['mass'])
            molecule_item.setBrush(QColor(*mass_color))

            self.scene.addItem(molecule_item)

    def getColorByMass(self, mass):
        min_mass = 1
        max_mass = 10

        min_color = QColor(0, 0, 255)  # Blue
        max_color = QColor(255, 0, 0)  # Red

        ratio = (mass - min_mass) / (max_mass - min_mass)

        r = int(min_color.red() + ratio * (max_color.red() - min_color.red()))
        g = int(min_color.green() + ratio * (max_color.green() - min_color.green()))
        b = int(min_color.blue() + ratio * (max_color.blue() - min_color.blue()))

        return r, g, b

    def updateMass(self):
        massValue = self.massSlider.value()
        self.massLabel.setText(f"Mass: {massValue}")

    def updateRadius(self):
        radiusValue = self.radiusSlider.value()
        self.radiusLabel.setText(f"Radius: {radiusValue}")

    def updateTemperature(self):
        temperatureValue = self.temperatureSlider.value() / 10.0
        self.temperature = temperatureValue
        self.temperatureLabel.setText(f"Temperature: {temperatureValue}")

        for molecule in         self.molecules:
            molecule['vx'] = random.uniform(-1, 1) * math.sqrt(3 * temperatureValue / molecule['mass'])
            molecule['vy'] = random.uniform(-1, 1) * math.sqrt(3 * temperatureValue / molecule['mass'])

    def timerEvent(self, event):
        for i in range(len(self.molecules)):
            molecule = self.molecules[i]
            molecule_item = self.scene.items()[i]

            molecule['x'] += molecule['vx']
            molecule['y'] += molecule['vy']

            molecule_item.setRect(
                molecule['x'] - molecule['radius'],
                molecule['y'] - molecule['radius'],
                2 * molecule['radius'],
                2 * molecule['radius']
            )

            if molecule['x'] < molecule['radius'] or molecule['x'] > self.width() - molecule['radius']:
                molecule['vx'] *= -1
            if molecule['y'] < molecule['radius'] or molecule['y'] > self.height() - molecule['radius']:
                molecule['vy'] *= -1

            for j in range(i + 1, len(self.molecules)):
                other_molecule = self.molecules[j]
                dx = other_molecule['x'] - molecule['x']
                dy = other_molecule['y'] - molecule['y']
                distance = math.sqrt(dx ** 2 + dy ** 2)

                if distance < molecule['radius'] + other_molecule['radius']:
                    mass_sum = molecule['mass'] + other_molecule['mass']
                    dx_normalized = dx / distance
                    dy_normalized = dy / distance

                    v1x = molecule['vx']
                    v1y = molecule['vy']

                    v2x = other_molecule['vx']
                    v2y = other_molecule['vy']

                    u1 = v1x * dx_normalized + v1y * dy_normalized
                    u2 = v2x * dx_normalized + v2y * dy_normalized

                    v1 = ((molecule['mass'] - other_molecule['mass']) * u1 + 2 * other_molecule['mass'] * u2) / mass_sum
                    v2 = ((other_molecule['mass'] - molecule['mass']) * u2 + 2 * molecule['mass'] * u1) / mass_sum

                    molecule['vx'] += (v1 - u1) * dx_normalized
                    molecule['vy'] += (v1 - u1) * dy_normalized
                    other_molecule['vx'] += (v2 - u2) * dx_normalized
                    other_molecule['vy'] += (v2 - u2) * dy_normalized

            molecule['x'] += random.uniform(-0.5, 0.5)
            molecule['y'] += random.uniform(-0.5, 0.5)

        self.view.viewport().update()

    def stopProgram(self):
        self.timer.stop() 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = GasMoleculeWindow()
    window.show()
    app.exec_()

When you press the Addmolecule button in the Ui, molecules should be displayed randomly on the Ui. However, it doesn't work. I need help.... No errors displayted on the Terminal(Using Visual studio) But I can't see the Molecules on the Ui....

1 Answers1

0

The QGraphicsView instance self.view is created but never set to be the central widget of the main window.

Lets just set the QGraphicsView to be the central widget of your QMainWindow.

class GasMoleculeWindow(QMainWindow, form_ui):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
         
        self.setWindowTitle("Gas Molecule Simulation")
        self.setGeometry(100, 100, 800, 600)

        self.molecules = []
        self.temperature = 1.0

        self.addMoleculeButton.clicked.connect(self.addMolecule)
        self.stopSimulation.clicked.connect(self.stopProgram)
        self.massSlider.setRange(1,10)
        self.massSlider.valueChanged.connect(self.updateMass)
        self.radiusSlider.valueChanged.connect(self.updateRadius)
        self.temperatureSlider.valueChanged.connect(self.updateTemperature)

        self.massLabel.setAlignment(Qt.AlignCenter)
        self.radiusLabel.setAlignment(Qt.AlignCenter)
        self.temperatureLabel.setAlignment(Qt.AlignCenter)

        self.scene = QGraphicsScene(self)
        self.view = QGraphicsView(self.scene)
        self.setCentralWidget(self.view)  # Set the QGraphicsView to be the central widget

        self.timer = self.startTimer(10)
Saxtheowl
  • 4,136
  • 5
  • 23
  • 32