How do I plot time series data with date/time axis labels in PyQtGraph, and how can I get this working when using Qt Designer's promoted widgets?
When working with real-world data, you'll often need to plot values against timestamps — stock prices over days, sensor readings over hours, or server logs over minutes. PyQtGraph makes this straightforward with its DateAxisItem, which converts Unix timestamps into human-readable date and time labels on your plot axis.
In this tutorial, we'll walk through how to plot time series data using PyQtGraph, first in a simple standalone script, then inside a Qt Designer–promoted PlotWidget. By the end, you'll have a complete, working example you can adapt for your own projects.
What is a Unix timestamp?
Before we start plotting, it helps to understand how PyQtGraph handles dates. PyQtGraph doesn't work with Python datetime objects directly. Instead, it uses Unix timestamps — the number of seconds since January 1, 1970 (UTC).
Python's datetime module can convert between human-readable dates and timestamps easily:
from datetime import datetime
dt = datetime(2025, 3, 15, 10, 30, 0)
timestamp = dt.timestamp()
print(timestamp) # e.g. 1742035800.0
When you pass these timestamp values as your x-axis data, PyQtGraph's DateAxisItem will format them into readable date/time labels automatically.
A simple time series plot
Let's start with a minimal example that plots some data points against dates. If you're new to PyQtGraph, you may want to read our introduction to plotting with PyQtGraph first.
import sys
from datetime import datetime
import pyqtgraph as pg
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
# Create some sample time series data.
timestamps = [
datetime(2025, 1, 1).timestamp(),
datetime(2025, 2, 1).timestamp(),
datetime(2025, 3, 1).timestamp(),
datetime(2025, 4, 1).timestamp(),
datetime(2025, 5, 1).timestamp(),
]
values = [10, 25, 18, 35, 30]
# Create a DateAxisItem for the bottom axis.
date_axis = pg.DateAxisItem()
# Create the PlotWidget, passing the DateAxisItem.
plot_widget = pg.PlotWidget(axisItems={"bottom": date_axis})
plot_widget.setWindowTitle("Time Series Example")
plot_widget.setLabel("left", "Value")
plot_widget.setLabel("bottom", "Date")
plot_widget.plot(timestamps, values, pen="b", symbol="o")
plot_widget.show()
sys.exit(app.exec_())
Run this and you'll see a plot with nicely formatted date labels on the x-axis. The DateAxisItem handles all the formatting, choosing appropriate labels based on the zoom level (years, months, days, hours, etc.).

Using DateAxisItem inside a QMainWindow
In most real applications, you won't just show a bare PlotWidget — you'll embed it inside a window with other widgets. Here's how that looks inside a QMainWindow:
PyQt/PySide Development Services — Stuck in development hell? I'll help you get your project focused, finished and released. Benefit from years of practical experience releasing software with Python.
import sys
from datetime import datetime
import pyqtgraph as pg
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Time Series in QMainWindow")
# Create sample data.
self.timestamps = [
datetime(2025, 1, 1).timestamp(),
datetime(2025, 2, 1).timestamp(),
datetime(2025, 3, 1).timestamp(),
datetime(2025, 4, 1).timestamp(),
datetime(2025, 5, 1).timestamp(),
datetime(2025, 6, 1).timestamp(),
]
self.values = [12, 28, 15, 33, 42, 38]
# Create DateAxisItem and PlotWidget.
date_axis = pg.DateAxisItem()
self.graph_widget = pg.PlotWidget(axisItems={"bottom": date_axis})
self.graph_widget.setLabel("left", "Temperature (°C)")
self.graph_widget.setLabel("bottom", "Date")
self.graph_widget.setTitle("Monthly Temperatures")
self.graph_widget.plot(
self.timestamps, self.values, pen="r", symbol="o", symbolBrush="r"
)
# Set up layout.
layout = QVBoxLayout()
layout.addWidget(self.graph_widget)
central_widget = QWidget()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
This works exactly as you'd expect. The DateAxisItem is passed in when creating the PlotWidget, and the widget is added to the window layout like any other Qt widget.
The Qt Designer challenge
Here's where things get a bit tricky, and where many people get stuck. When you use Qt Designer to design your interface, you typically promote a QGraphicsView (or QWidget) to pg.PlotWidget. Qt Designer creates the widget for you — but it doesn't give you any way to pass axisItems as a constructor argument.
That's why this pattern doesn't work when using Qt Designer:
# This works when YOU create the widget...
self.graph_widget = pg.PlotWidget(axisItems={"bottom": date_axis})
# ...but if Qt Designer already created self.graphicsView,
# you can't pass constructor arguments to it.
The widget already exists by the time your __init__ method runs. You need a different approach.
Replacing the axis after creation
The solution is to set the DateAxisItem on the plot after the widget has been created. You can do this by calling setAxisItems():
date_axis = pg.DateAxisItem()
self.graphicsView.setAxisItems({"bottom": date_axis})
The setAxisItems() method replaces the existing axis with your new one. This works whether the PlotWidget was created in your code or by Qt Designer's generated UI file.
Using DateAxisItem with Qt Designer
Let's put this into practice with a complete Qt Designer workflow.
Setting up the .ui file
- Open Qt Designer and create a new Main Window.
- Drag a
QGraphicsViewonto the central widget. - Right-click the
QGraphicsViewand select Promote to.... - Fill in the promotion dialog:
- Promoted class name:
PlotWidget - Header file:
pyqtgraph - Click Add, then Promote.
- Save the file as
mainwindow.ui.
If you're not familiar with promoting widgets in Qt Designer, the basic idea is that you're telling Qt to use pyqtgraph.PlotWidget instead of the plain QGraphicsView at runtime. For a full walkthrough of embedding custom widgets via promotion, see our guide to embedding PyQtGraph in Qt applications.
The complete code
Here's a full working example that loads a .ui file and adds a time series plot with proper date axis labels:
import sys
from datetime import datetime
import pyqtgraph as pg
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi("mainwindow.ui", self)
# Replace the bottom axis with a DateAxisItem.
# This works even though Qt Designer already created the widget.
date_axis = pg.DateAxisItem()
self.graphicsView.setAxisItems({"bottom": date_axis})
# Create sample time series data.
timestamps = [
datetime(2025, 1, 15).timestamp(),
datetime(2025, 2, 15).timestamp(),
datetime(2025, 3, 15).timestamp(),
datetime(2025, 4, 15).timestamp(),
datetime(2025, 5, 15).timestamp(),
datetime(2025, 6, 15).timestamp(),
]
values = [22, 19, 25, 31, 37, 42]
# Configure and plot.
self.graphicsView.setLabel("left", "Value")
self.graphicsView.setLabel("bottom", "Date")
self.graphicsView.setTitle("Time Series from Qt Designer")
self.graphicsView.plot(timestamps, values, pen="g", symbol="o")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
The promoted widget from Qt Designer is accessible as self.graphicsView (or whatever object name you gave it in Designer). After loading the UI, we call setAxisItems() to swap in the DateAxisItem — and from that point on, everything works as normal.
If you renamed the widget in Qt Designer (for example, to
plotWidget), use that name instead:self.plotWidget.setAxisItems(...).
Without Qt Designer
If you're not using Qt Designer but still want to build a time series plot inside a custom window class, you have two equally valid options.
Option 1: Pass axisItems at creation time.
date_axis = pg.DateAxisItem()
self.graph_widget = pg.PlotWidget(axisItems={"bottom": date_axis})
Option 2: Create the widget first, then replace the axis.
self.graph_widget = pg.PlotWidget()
date_axis = pg.DateAxisItem()
self.graph_widget.setAxisItems({"bottom": date_axis})
Both produce identical results. Option 2 is useful to know because it's the same pattern you need when working with Qt Designer.
Complete example with live updating data
To bring everything together, here's a more realistic example. This creates a time series plot that updates with new data points every second, simulating a live data feed — like a temperature sensor or stock ticker. The live update is driven by a QTimer, which calls our update_plot method at regular intervals. For more on handling background tasks and timers in PyQt5, see our multithreading with QThreadPool tutorial.
import sys
from datetime import datetime
from collections import deque
import numpy as np
import pyqtgraph as pg
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
class LiveTimeSeriesWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Live Time Series Plot")
self.resize(800, 400)
# Store the last 60 data points.
self.max_points = 60
self.timestamps = deque(maxlen=self.max_points)
self.values = deque(maxlen=self.max_points)
# Create the plot with a DateAxisItem.
date_axis = pg.DateAxisItem()
self.graph_widget = pg.PlotWidget(axisItems={"bottom": date_axis})
self.graph_widget.setLabel("left", "Sensor Value")
self.graph_widget.setLabel("bottom", "Time")
self.graph_widget.setTitle("Live Sensor Data")
self.graph_widget.addLegend()
# Create the plot data item (empty for now).
self.data_line = self.graph_widget.plot(
[], [], pen=pg.mkPen("c", width=2), name="Sensor 1"
)
# Layout.
layout = QVBoxLayout()
layout.addWidget(self.graph_widget)
central_widget = QWidget()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
# Timer to add new data every second.
self.timer = QTimer()
self.timer.timeout.connect(self.update_plot)
self.timer.start(1000)
# Seed with a starting value.
self.current_value = 20.0
def update_plot(self):
# Generate a new data point.
now = datetime.now().timestamp()
self.current_value += np.random.normal(0, 0.5) # Random walk.
self.timestamps.append(now)
self.values.append(self.current_value)
# Update the plot.
self.data_line.setData(list(self.timestamps), list(self.values))
app = QApplication(sys.argv)
window = LiveTimeSeriesWindow()
window.show()
sys.exit(app.exec_())
Run this and you'll see data points appearing in real time, with the x-axis showing the current time formatted by DateAxisItem. As the window fills with 60 points, older data scrolls off the left side thanks to the deque with a maxlen.
Summary
Plotting time series data in PyQtGraph comes down to two things:
- Use Unix timestamps for your x-axis values. Convert from Python
datetimeobjects using.timestamp(). - Use
DateAxisItemto display those timestamps as formatted dates on the axis.
When creating the PlotWidget yourself, you can pass axisItems={"bottom": date_axis} directly. When working with Qt Designer (where the widget is already created for you), use setAxisItems() to swap in the DateAxisItem after loading the UI. Both approaches give you the same result — a clean, readable time series plot with properly formatted date and time labels.
If you also want to plot with Matplotlib inside a PyQt5 application, check out our Matplotlib plotting tutorial.
Purchasing Power Parity
Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick
(PyQt5 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!