diff --git a/b_asic/scheduler-gui/graphics_axis_item.py b/b_asic/scheduler-gui/graphics_axis_item.py
index 3bd84fab309ceacd7ec7541e913869b50a6fd53b..a237c6607861dea07589a5e5a0540a6136534be3 100644
--- a/b_asic/scheduler-gui/graphics_axis_item.py
+++ b/b_asic/scheduler-gui/graphics_axis_item.py
@@ -1,12 +1,15 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
+"""B-ASIC Scheduler-gui Graphics Axis Item Module.
 
+Contains the scheduler-gui axis class for drawing and maintain the axis in a graph.
+"""
 from operator import contains
 import os
 import sys
 from typing     import Any, Optional
 from pprint     import pprint
-from typing     import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
+from typing     import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final, Dict
 # from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
 import numpy    as np
 from copy       import deepcopy
@@ -19,7 +22,7 @@ from qtpy import QtWidgets
 
 # QGraphics and QPainter imports
 from qtpy.QtCore    import (
-    Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray)
+    Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray, qAbs)
 from qtpy.QtGui     import (
     QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
     QLinearGradient, QTransform, QPolygonF)
@@ -38,71 +41,95 @@ from graphics_graph_event   import GraphicsGraphEvent
 
 
 class GraphicsAxisItem(QGraphicsItemGroup):
-
-    _scale:     float = 1.0 # static, changed from MainWindow
-    _width:     float
-    _height:    float
-    _dy_height: float
-    _x_indent:  float
-    _axis:      dict[str, QGraphicsItemGroup|QGraphicsLineItem]
-
-    def __init__(self, width: float = 1.0, height: float = 1.0, x_indent: float = 0.2, parent: QGraphicsItem = None):
+    """A class to represent axis in a graph."""
+    _scale:         float = 1.0
+    """Static, changed from MainWindow."""
+    _width_padding: float
+    _width:         float
+    _height:        float
+    _dy_height:     float
+    _x_indent:      float
+    _axis:          Dict[str, Union[QGraphicsItemGroup, QGraphicsLineItem]]
+
+    def __init__(self, width: float, height: float, x_indent: float  = 0.2, parent: Optional[QGraphicsItem] = None):
+        """Constructs a GraphicsAxisItem. 'parent' is passed to QGraphicsItemGroup's constructor."""
         super().__init__(parent)
 
         self._dy_height = 5/self._scale
         self._axis = {}
-        # self.setFlag(QGraphicsItem.ItemIsMovable)
-        # self.setFlag(QGraphicsItem.ItemIsSelectable)
-        # self.setAcceptHoverEvents(True)
+        self._width_padding = 0.6
+        self._width = width + self._width_padding
+        self._height = height
+        self._x_indent = x_indent
 
-        self.update_(width + 0.6, height, x_indent)
-    
+        self._make_axis()
 
-    @property
-    def width(self) -> float:
-        return self._axis['w']
-    # @width.setter
-    # def width(self, width: float) -> None:
-    #     self._axis['w'] = width
-    #     self.prepareGeometryChange()
-    #     self._axis.clear()
-    #     self._make_axis()
 
-    @property
-    def height(self) -> float:
-        return self._axis['h']
-    # @height.setter
-    # def height(self, height: float) -> None:
-    #     self._axis['h'] = height
-    #     self.prepareGeometryChange()
-    #     self._axis.clear()
-    #     self._make_axis()
-
-    # def _clear(self) -> None:
-    #     for child in self._axis.values():
-    #         del child
-
-    def update_(self, width, height, x_indent) -> None:
-        self._width = width
-        self._height = height
-        self._x_indent = x_indent
-        
-        # make sure the group is empty
+    def clear(self) -> None:
+        """Sets all children's parent to 'None' and delete the axis."""
         keys = list(self._axis.keys())
         for key in keys:
+            print(f'clear() key: {key}')
             self._axis[key].setParentItem(None)
             del self._axis[key]
+    
+
+    @property
+    def width(self) -> float:
+        """Get or set the current x-axis width. Setting the width to a new
+        value will update the axis automatically."""
+        return self._width
+    @width.setter
+    def width(self, width: float) -> None:
+        if self._width != width + self._width_padding:
+            self._width = width + self._width_padding
+            self.update_axis()
 
-        # define pencils
+    @property
+    def height(self) -> float:
+        """Get or set the current y-axis height. Setting the height to a new
+        value will update the axis automatically."""
+        return self._height
+    @height.setter
+    def height(self, height: float) -> None:
+        if self._height != height:
+            self._height = height
+            self.update_axis()
+    
+    @property
+    def x_indent(self) -> float:
+        """Get or set the current x-axis indent. Setting the indent to a new
+        value will update the axis automatically."""
+        return self._x_indent
+    @x_indent.setter
+    def x_indent(self, x_indent: float) -> None:
+        if self._x_indent != x_indent:
+            self._x_indent = x_indent
+            self.update_axis()
+
+
+    def update_axis(self, width: Optional[float] = None, height: Optional[float] = None, x_indent: Optional[float] = None) -> None:
+        """Updates the current axis with the new 'width', 'height' and 'x_indent'. If any of the
+        parameters is omitted, the stored value will be used."""
+        if width is not None:    self._width = width + self._width_padding
+        if height is not None:   self._height = height
+        if x_indent is not None: self._x_indent = x_indent
+        self.clear()                    # make sure the group is empty
+        self._make_axis()               # make new axis
+
+
+    def _make_axis(self) -> None:
+        """Makes new axis out of the stored attributes."""
+        ## define pencils
         pen = QPen()
         pen.setWidthF(2/self._scale)
         pen.setJoinStyle(Qt.MiterJoin)
         ledger_pen = QPen(Qt.lightGray)
         ledger_pen.setWidthF(0)         # 0 = cosmetic pen 1px width
         
-        # x-axis
+        ## x-axis
         self._axis['x'] = QGraphicsItemGroup()
-        line = QGraphicsLineItem(0, 0, self._width, 0)
+        line = QGraphicsLineItem(0, 0, self.width, 0)
         line.setPen(pen)
         self._axis['x'].addToGroup(line)
         # x-axis arrow
@@ -114,51 +141,51 @@ class GraphicsAxisItem(QGraphicsItemGroup):
         arrow = QGraphicsPolygonItem(polygon)
         arrow.setPen(pen)
         arrow.setBrush(QBrush(Qt.SolidPattern))
-        arrow.setPos(self._width, 0)
+        arrow.setPos(self.width, 0)
         self._axis['x'].addToGroup(arrow)
         # x-axis scale
         x_scale = []
         x_scale_labels = []
         x_ledger = []
         self._axis['x_ledger'] = QGraphicsItemGroup()
-        for i in range(int(self._width) + 1):
+        for i in range(int(self.width) + 1):
+            x_pos = QPointF(self.x_indent + i, 0)
             # vertical x-scale
             x_scale.append(QGraphicsLineItem(0, 0, 0, 0.05))
             x_scale[i].setPen(pen)
-            x_scale[i].setPos(self._x_indent + i, 0)
+            x_scale[i].setPos(x_pos)
             self._axis['x'].addToGroup(x_scale[i])
             # numbers
             x_scale_labels.append(QGraphicsSimpleTextItem(str(i)))
             x_scale_labels[i].setScale(x_scale_labels[i].scale() / self._scale)
-            half_width = x_scale_labels[i].boundingRect().width()/(2*self._scale)
-            x_scale_labels[i].setPos(self._x_indent + i - half_width, 0.08)
+            center = x_pos - self.mapFromItem(x_scale_labels[i], x_scale_labels[i].boundingRect().center())
+            x_scale_labels[i].setPos(center + QPointF(0, 0.2))
             self._axis['x'].addToGroup(x_scale_labels[i])
             # vertical x-ledger
-            x_ledger.append(QGraphicsLineItem(0, 0, 0, self._height))
-            if i == int(self._width):
+            x_ledger.append(QGraphicsLineItem(0, 0, 0, self.height))
+            if i == int(self.width):                                       # last line is special
                 ledger_pen.setWidthF(2/self._scale)
                 ledger_pen.setStyle(Qt.DashLine)
                 ledger_pen.setColor(Qt.black)
             x_ledger[i].setPen(ledger_pen)
-            x_ledger[i].setPos(self._x_indent + i, 0)
+            x_ledger[i].setPos(x_pos)
             self._axis['x_ledger'].addToGroup(x_ledger[i])
         # x-axis label
         label = QGraphicsSimpleTextItem('time')
         label.setScale(label.scale() / self._scale)
-        half_width = label.boundingRect().width()/(2*self._scale)
-        arrow_half_width = arrow_size/2
-        label.setPos(self._width - half_width + arrow_half_width, 0.08)
+        center = self.mapFromItem(arrow, arrow.boundingRect().center())     # =center of arrow
+        center -= self.mapFromItem(label, label.boundingRect().center())    # -center of label
+        label.setPos(center + QPointF(0, 0.2))                              # move down under arrow
         self._axis['x'].addToGroup(label)
-        self._axis['x'].boundingRect()
 
         # y-axis
-        self._axis['y'] = QGraphicsLineItem(0, 0, 0, self._height + self._dy_height)
+        self._axis['y'] = QGraphicsLineItem(0, 0, 0, self.height + self._dy_height)
         self._axis['y'].setPen(pen)
         
         # put it all together
-        self._axis['x'].setPos(0, self._height + self._dy_height)
         self._axis['x_ledger'].setPos(0, self._dy_height)
         self.addToGroup(self._axis['x_ledger'])
+        self._axis['x'].setPos(0, self.height + self._dy_height)
         self.addToGroup(self._axis['x'])
         self.addToGroup(self._axis['y'])
         
\ No newline at end of file
diff --git a/b_asic/scheduler-gui/graphics_component_item.py b/b_asic/scheduler-gui/graphics_component_item.py
index 16003628185791131b038b0b45d603b4767fce25..929a9b5d66c2606393536b3d0f017458aec8771e 100644
--- a/b_asic/scheduler-gui/graphics_component_item.py
+++ b/b_asic/scheduler-gui/graphics_component_item.py
@@ -37,7 +37,8 @@ from graphics_component_event import GraphicsComponentEvent
 
 class GraphicsComponentItem(QGraphicsItemGroup):
     
-    _scale:                 float = 1.0 # static, changed from MainWindow
+    _scale:                 float = 1.0
+    """Static, changed from MainWindow."""
     _op_id:                 str
     _height:                float
     # _input_ports_latency:   Dict[str, int]
@@ -52,7 +53,7 @@ class GraphicsComponentItem(QGraphicsItemGroup):
     _item_group:            QGraphicsItemGroup
     
     
-    def __init__(self, op_id: str, latency_offsets: Dict[str, int], execution_time: Union[int, None] = None, height: float = 1.0, parent: QGraphicsItem = None):
+    def __init__(self, op_id: str, latency_offsets: Dict[str, int], execution_time: Optional[int] = None, height: float = 1.0, parent: Optional[QGraphicsItem] = None):
         super().__init__(parent)
 
         self._op_id = op_id
@@ -113,11 +114,11 @@ class GraphicsComponentItem(QGraphicsItemGroup):
             # register the port pos in dictionary
             port_x = x
             port_y = y - abs(y - old_y)/2   # port coord is at the center of previous line
-            self._input_ports[key]['pos'] = QPoint(port_x, port_y)
+            self._input_ports[key]['pos'] = QPointF(port_x, port_y)
             # update last pos
             old_x = x
             old_y = y
-            print(f'{key}({x}, {y})\tport({port_x}, {port_y})')
+            print(f"{key}({x}, {y})\tport({self._input_ports[key]['pos'].x()}, {self._input_ports[key]['pos'].y()})")
         
         # draw inport side lines
         for i in range(len(output_list)):
@@ -131,38 +132,46 @@ class GraphicsComponentItem(QGraphicsItemGroup):
             # register the port pos in dictionary
             port_x = x
             port_y = y + abs(y - old_y)/2   # port coord is at the center of previous line
-            self._output_ports[key]['pos'] = QPoint(port_x, port_y)
+            self._output_ports[key]['pos'] = QPointF(port_x, port_y)
             # update last pos
             old_x = x
             old_y = y
-            print(f'{key}({x}, {y})\tport({port_x}, {port_y})')
+            print(f"{key}({x}, {y})\tport({self._output_ports[key]['pos'].x()}, {self._output_ports[key]['pos'].y()})")
             
         component_path.closeSubpath()
         
         ## ports item
+        brush2 = QBrush(Qt.darkGray)
         pen2 = QPen(Qt.darkGray)
-        pen2.setWidthF(2/self._scale)
-        brush2 = QBrush(Qt.black)
+        pen2.setWidthF(0)
+        # pen2.setCosmetic(True)
         port_items = []
+        size = 8/self._scale
         for key in self._input_ports:
             port_pos = self.mapToParent(self._input_ports[key]['pos'])
-            
-            port = QGraphicsEllipseItem(port_pos.x(), port_pos.y(), 1/self._scale, 1/self._scale)
+            # port = QGraphicsEllipseItem(port_pos.x(), port_pos.y(), 10/self._scale, 10/self._scale)
+            port = QGraphicsEllipseItem(-size/2, -size/2, size, size)   # center of circle is in origo
             port_items.append(port)
             # port_items[-1].setPos(self._input_ports[key]['pos'])
             # port_items[-1].setScale(0.5)
-            # port_items[-1].setPen(pen2)
+            port_items[-1].setPen(pen2)
             # print(port_items[-1])
-            # port_items[-1].setBrush(brush2)
-            # port_items[-1].setPos(1, 0.5)
-            break
+            port_items[-1].setBrush(brush2)
+            port_items[-1].setPos(port_pos.x(), port_pos.y())
+        
+        for key in self._output_ports:
+            port_pos = self.mapToParent(self._output_ports[key]['pos'])
+            port = QGraphicsEllipseItem(-size/2, -size/2, size, size)   # center of circle is in origo
+            port_items.append(port)
+            port_items[-1].setPen(pen2)
+            port_items[-1].setBrush(brush2)
+            port_items[-1].setPos(port_pos.x(), port_pos.y())
 
 
         ## component item
         self._component_item.setPath(component_path)
         self._component_item.setPen(pen)
         self._component_item.setBrush(brush)
-        # self._component_item.setPos(1, 0)      # in parent (i.e. self) coordinates
 
         ## op-id/label
         label = QGraphicsSimpleTextItem(self._op_id)
@@ -181,6 +190,7 @@ class GraphicsComponentItem(QGraphicsItemGroup):
             green_color = QColor(Qt.magenta)
             green_color.setAlpha(200)               # 0-255
             pen.setColor(green_color)
+            pen.setWidthF(3/self._scale)
             self._execution_time_item = QGraphicsPathItem(execution_time_path)
             self._execution_time_item.setPen(pen)
         
diff --git a/b_asic/scheduler-gui/graphics_graph_event.py b/b_asic/scheduler-gui/graphics_graph_event.py
index b908d432eae63258df45b61d3adeb7eac3979412..15a2baea816feb2c49c64cfbd22a0d011397da16 100644
--- a/b_asic/scheduler-gui/graphics_graph_event.py
+++ b/b_asic/scheduler-gui/graphics_graph_event.py
@@ -83,7 +83,6 @@ class GraphicsGraphEvent(QGraphicsItem):
         # self.setFiltersChildEvents(False)
         
     
-    # def sceneEventFilter(self, item: QGraphicsItem, event: QEvent) -> bool:
     def sceneEventFilter(self, item: QGraphicsItem, event: QEvent) -> bool:
         """Returns true if the event was filtered (i.e. stopped), otherwise false.
         If false is returned, the event is forwarded to the appropriate child in
diff --git a/b_asic/scheduler-gui/graphics_graph_item.py b/b_asic/scheduler-gui/graphics_graph_item.py
index a1b41c6166769936d0b6e03bcbc91bf2c12b29e9..e3a500625090f1932b057890cbbb7453d6a79864 100644
--- a/b_asic/scheduler-gui/graphics_graph_item.py
+++ b/b_asic/scheduler-gui/graphics_graph_item.py
@@ -4,7 +4,7 @@ import os
 import sys
 from typing     import Any, Optional
 from pprint     import pprint
-from typing     import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
+from typing     import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final, List
 # from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
 import numpy    as np
 from copy       import deepcopy
@@ -45,12 +45,12 @@ class GraphicsGraphItem(QGraphicsItemGroup, GraphicsGraphEvent):
     
     _schedule:          Schedule
     _axis:              GraphicsAxisItem
-    _components:   list[GraphicsComponentItem]
+    _components:        List[GraphicsComponentItem]
     _components_height: float
     _x_axis_indent:     float
 
     
-    def __init__(self, schedule: Schedule, parent: QGraphicsItem = None):
+    def __init__(self, schedule: Schedule, parent: Optional[QGraphicsItem] = None):
         super().__init__(parent)
 
         self._schedule = deepcopy(schedule)
@@ -68,7 +68,7 @@ class GraphicsGraphItem(QGraphicsItemGroup, GraphicsGraphEvent):
             
             if not isinstance(op, (Input, Output)):
                 self._components_height += spacing
-                component = GraphicsComponentItem(op_id, op.latency_offsets, op.execution_time)
+                component = GraphicsComponentItem(op_id, op.latency_offsets, op.execution_time, 0.75)
                 component.setPos(self._x_axis_indent + op_start_time, self._components_height)
                 self._components.append(component)
                 self._components_height += component.height
@@ -77,9 +77,11 @@ class GraphicsGraphItem(QGraphicsItemGroup, GraphicsGraphEvent):
         # build axis
         schedule_time = self.schedule.schedule_time
         self._axis = GraphicsAxisItem(schedule_time, self._components_height, self._x_axis_indent)
+        self._axis.width = schedule_time
 
         # add axis and components
         self.addToGroup(self._axis)
+        # self._axis.update_axis(schedule_time - 2, self._components_height, self._x_axis_indent)
         for component in self._components:
             self.addToGroup(component)
         # self.addToGroup(self._components)
diff --git a/b_asic/scheduler-gui/logger.py b/b_asic/scheduler-gui/logger.py
index 113b631c534fb3e8c6cb5bac8bf147006252052e..2c40500bf357b2b6f0ba2a1a41b4be4b78831c63 100644
--- a/b_asic/scheduler-gui/logger.py
+++ b/b_asic/scheduler-gui/logger.py
@@ -37,6 +37,7 @@ from logging import Logger
 import logging
 import logging.handlers
 import traceback
+from qtpy import QtCore, QtWidgets
 
 
 def getLogger(filename: str='scheduler-gui.log', loglevel: str='INFO') -> Logger:
@@ -100,3 +101,20 @@ def handle_exceptions(exc_type: Type[BaseException], exc_value: BaseException, e
         return
 
     logging.exception("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
+
+def qt_message_handler(mode, context, message):
+    if mode == QtCore.QtInfoMsg:
+        mode = 'INFO'
+    elif mode == QtCore.QtWarningMsg:
+        mode = 'WARNING'
+    elif mode == QtCore.QtCriticalMsg:
+        mode = 'CRITICAL'
+    # elif mode == QtCore.QtErrorMsg:
+    #     mode = 'ERROR'
+    elif mode == QtCore.QtFatalMsg:
+        mode = 'FATAL'
+    else:
+        mode = 'DEBUG'
+    print('qt_message_handler: line: %d, func: %s(), file: %s' % (
+          context.line, context.function, context.file))
+    print('  %s: %s\n' % (mode, message))
diff --git a/b_asic/scheduler-gui/main_window.py b/b_asic/scheduler-gui/main_window.py
index bf887e7ec769d7e8c02b3b3e0dc6cea3dfcb1063..b3dec33a415e14747bb6134ffd1e93d392ad2275 100644
--- a/b_asic/scheduler-gui/main_window.py
+++ b/b_asic/scheduler-gui/main_window.py
@@ -57,6 +57,7 @@ from graphics_component_item    import GraphicsComponentItem
 log = logger.getLogger()
 sys.excepthook = logger.handle_exceptions
 
+
 # Debug struff
 if __debug__:
     log.setLevel('DEBUG')
@@ -331,7 +332,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             self.menu_node_info.setChecked(True)
         
     @Slot('QList<QRectF>')
-    def shrink_scene_to_min_size(self, region: list[QRectF]) -> None:
+    def shrink_scene_to_min_size(self, region: List[QRectF]) -> None:
         self._scene.setSceneRect(self._scene.itemsBoundingRect())