I want to put Amplitude slider and hello button on the right hand side. I want to create a horizontal layout but with matplotlib widget and frequency slider be in vertical layout of each other. The amplitude slider and hello button also in vertical layout of each other. I want something like this.
Thank for the help.
#!/usr/bin/python3
import sys
import numpy as np
import matplotlib.pyplot as plt
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QSlider, QLabel, QPushButton, QFileDialog, QDialog, QHBoxLayout
from PyQt5.QtCore import Qt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class SinewaveApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Sine Wave with Frequency and Amplitude Sliders")
self.setGeometry(100, 100, 800, 600)
self.central_widget = QWidget(self)
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout(self.central_widget)
self.create_widgets()
self.setup_plot()
def create_widgets(self):
# Graph area
self.figure, self.ax = plt.subplots()
self.canvas = FigureCanvas(self.figure)
self.layout.addWidget(self.canvas)
# Sliders and hello Box Layout
right_layout = QHBoxLayout()
# Sliders area
left_layout = QVBoxLayout()
# Frequency Slider
self.freq_slider_label = QLabel("Frequency:")
left_layout.addWidget(self.freq_slider_label)
self.freq_slider = QSlider()
self.freq_slider.setOrientation(Qt.Horizontal)
self.freq_slider.setMinimum(1)
self.freq_slider.setMaximum(10)
self.freq_slider.setTickInterval(1)
self.freq_slider.setTickPosition(QSlider.TicksBothSides)
left_layout.addWidget(self.freq_slider)
# Add sliders layout to the sliders and hello layout
right_layout.addLayout(left_layout)
# Amplitude Slider
self.amp_slider_label = QLabel("Amplitude:")
right_layout.addWidget(self.amp_slider_label)
self.amp_slider = QSlider()
self.amp_slider.setOrientation(Qt.Horizontal)
self.amp_slider.setMinimum(1)
self.amp_slider.setMaximum(10)
self.amp_slider.setTickInterval(1)
self.amp_slider.setTickPosition(QSlider.TicksBothSides)
right_layout.addWidget(self.amp_slider)
# hello button
self.button = QPushButton("hello", self)
right_layout.addWidget(self.button)
# Add the sliders and hello layout to the main layout
self.layout.addLayout(right_layout)
# Connect button to dialog
self.button.clicked.connect(self.show_hello_window)
# Connect sliders to plot update
self.freq_slider.valueChanged.connect(self.update_plot)
self.amp_slider.valueChanged.connect(self.update_plot)
def setup_plot(self):
self.x = np.linspace(0, 2 * np.pi, 1000)
self.freq = 1 # Initial frequency
self.amp = 1 # Initial amplitude
y = self.amp * np.sin(self.freq * self.x)
self.line, = self.ax.plot(self.x, y, label='Sine Wave')
self.ax.legend()
self.ax.set_xlabel('Time')
self.ax.set_ylabel('Amplitude')
self.canvas.draw()
def update_plot(self):
frequency = self.freq_slider.value()
amplitude = self.amp_slider.value()
y = amplitude * np.sin(frequency * self.x)
self.line.set_ydata(y)
self.canvas.draw()
def show_hello_window(self):
hello_dialog = helloDialog(self)
hello_dialog.exec_()
class helloDialog(QDialog):
def __init__(self, parent):
super().__init__(parent)
self.setWindowTitle("hello")
self.setGeometry(200, 200, 300, 150)
layout = QVBoxLayout()
label = QLabel("Say Hello", self)
layout.addWidget(label)
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = SinewaveApp()
mainWin.show()
sys.exit(app.exec_())
Your layouts are organized in the wrong way.
When complex layouts are required, you must consider things hierarchically: in your case, the top layout is a horizontal layout, but you're using QVBoxLayout instead.
For such a situation you may consider a combination of box and grid layouts.
+---------- main horizontal layout -----------+
| | |
| +----- grid -----+ | +----- vertical -----+ |
| | | | | | |
| | canvas | | | +-- horizontal --+ | |
| | | | | | label | slider | | |
| +-------+--------+ | | +-------+--------+ | |
| | | | | | | |
| | label | slider | | | button | |
| | | | | | | |
| +-------+--------+ | +--------------------+ |
+--------------------+------------------------+
So, consider the following changes:
class SinewaveApp(QMainWindow):
def __init__(self):
...
self.layout = QHBoxLayout(self.central_widget)
...
def create_widgets(self):
...
left_layout = QGridLayout()
self.layout.addLayout(left_layout, stretch=2)
left_layout.addWidget(self.canvas, 0, 0, 1, 2)
left_layout.addWidget(self.freq_slider_label, 1, 0)
left_layout.addWidget(self.freq_slider, 1, 1)
right_layout = QVBoxLayout()
self.layout.addLayout(right_layout, stretch=1)
right_top = QHBoxLayout()
right_layout.addLayout(right_top)
right_top.addWidget(self.amp_slider_label)
right_top.addWidget(self.amp_slider)
right_layout.addWidget(self.button, alignment=Qt.AlignLeft)
right_layout.setAlignment(Qt.AlignTop)