Index: src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java b/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java
--- a/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java	(revision 17579)
+++ b/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java	(date 1616172916652)
@@ -26,6 +26,7 @@
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.NoteInputDialog;
+import org.openstreetmap.josm.gui.widgets.LargeTextTable;
 import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmApi;
@@ -168,7 +169,7 @@
 
     private Component buildDiscussionPanel() {
         JPanel pnl = new JPanel(new BorderLayout());
-        table = new JTable(model, new ChangesetDiscussionTableColumnModel());
+        table = new LargeTextTable(model, new ChangesetDiscussionTableColumnModel());
         table.setRowSorter(new ChangesetDiscussionTableRowSorter(model));
         table.getTableHeader().setReorderingAllowed(false);
 
Index: src/org/openstreetmap/josm/gui/widgets/LargeTextTable.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/gui/widgets/LargeTextTable.java b/src/org/openstreetmap/josm/gui/widgets/LargeTextTable.java
new file mode 100644
--- /dev/null	(date 1616172986796)
+++ b/src/org/openstreetmap/josm/gui/widgets/LargeTextTable.java	(date 1616172986796)
@@ -0,0 +1,69 @@
+package org.openstreetmap.josm.gui.widgets;
+
+import java.awt.FontMetrics;
+import java.awt.Rectangle;
+
+import javax.swing.JTable;
+import javax.swing.SwingConstants;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
+
+/**
+ * Table with a scrolling behavior that is better suited for cells with large amounts of text.
+ * <p>
+ * The scrolling in the {@link javax.swing.JTable} is well suited for tables with rows of small and constant height.
+ * If the height of the rows varies greatly or if some cells contain a lot of text, the scrolling becomes messy.
+ * <p>
+ * This class {@code LargeTextTable} has the same scrolling behavior as {@link javax.swing.JTextArea}:
+ * scrolling increments depend on the font size.
+ */
+public class LargeTextTable extends JTable {
+
+    private int fontHeight;
+    private int charWidth;
+
+    public LargeTextTable(TableModel tableModel, TableColumnModel tableColumnModel) {
+        super(tableModel, tableColumnModel);
+    }
+
+    @Override
+    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+        switch (orientation) {
+            case SwingConstants.VERTICAL:
+                return getFontHeight();
+            case SwingConstants.HORIZONTAL:
+                return getCharWidth();
+            default:
+                throw new IllegalArgumentException("Invalid orientation: " + orientation);
+        }
+    }
+
+    @Override
+    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+        switch (orientation) {
+            case SwingConstants.VERTICAL:
+                return visibleRect.height;
+            case SwingConstants.HORIZONTAL:
+                return visibleRect.width;
+            default:
+                throw new IllegalArgumentException("Invalid orientation: " + orientation);
+        }
+    }
+
+    private int getFontHeight() {
+        if (fontHeight == 0) {
+            FontMetrics fontMetrics = getFontMetrics(getFont());
+            fontHeight = fontMetrics.getHeight();
+        }
+        return fontHeight;
+    }
+
+    // see javax.swing.JTextArea#getColumnWidth()
+    private int getCharWidth() {
+        if (charWidth == 0) {
+            FontMetrics fontMetrics = getFontMetrics(getFont());
+            charWidth = fontMetrics.charWidth('m');
+        }
+        return charWidth;
+    }
+}
Index: test/unit/org/openstreetmap/josm/gui/widgets/LargeTextTableTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/unit/org/openstreetmap/josm/gui/widgets/LargeTextTableTest.java b/test/unit/org/openstreetmap/josm/gui/widgets/LargeTextTableTest.java
new file mode 100644
--- /dev/null	(date 1616173129657)
+++ b/test/unit/org/openstreetmap/josm/gui/widgets/LargeTextTableTest.java	(date 1616173129657)
@@ -0,0 +1,73 @@
+package org.openstreetmap.josm.gui.widgets;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Rectangle;
+
+import javax.swing.JTable;
+import javax.swing.SwingConstants;
+
+import org.junit.jupiter.api.Test;
+
+import sun.swing.SwingUtilities2;
+
+class LargeTextTableTest {
+    private JTable table = new LargeTextTable(null, null);
+    private Rectangle visibleRectangle = new Rectangle(0, 0, 101, 202);
+
+    @Test
+    void testGetScrollableBlockIncrementVertical() {
+        int scrollableBlockIncrement = table.getScrollableBlockIncrement(visibleRectangle, SwingConstants.VERTICAL, 0);
+
+        assertThat(scrollableBlockIncrement, is(202));
+    }
+
+    @Test
+    void testGetScrollableBlockIncrementHorizontal() {
+        int scrollableBlockIncrement = table.getScrollableBlockIncrement(visibleRectangle, SwingConstants.HORIZONTAL, 0);
+
+        assertThat(scrollableBlockIncrement, is(101));
+    }
+
+    @Test
+    void testGetScrollableBlockIncrementWithInvalidOrientation() {
+        assertThrows(IllegalArgumentException.class,
+                () -> table.getScrollableBlockIncrement(visibleRectangle, -11, 0));
+    }
+
+    @Test
+    void testGetScrollableUnitIncrementVertical() {
+        Font font = new Font("", Font.PLAIN, 10);
+        table.setFont(font);
+
+        int actualIncrement = table.getScrollableUnitIncrement(visibleRectangle, SwingConstants.VERTICAL, 0);
+        int expectedIncrement = getFontMetrics(font).getHeight();
+
+        assertThat(actualIncrement, is(expectedIncrement));
+    }
+
+    @Test
+    void testGetScrollableUnitIncrementHorizontal() {
+        Font font = new Font("", Font.PLAIN, 10);
+        table.setFont(font);
+
+        int actualIncrement = table.getScrollableUnitIncrement(visibleRectangle, SwingConstants.HORIZONTAL, 0);
+        int expectedIncrement = getFontMetrics(font).charWidth('m');
+
+        assertThat(actualIncrement, is(expectedIncrement));
+    }
+
+    private FontMetrics getFontMetrics(Font font) {
+        return SwingUtilities2.getFontMetrics(table, font);
+    }
+
+    @Test
+    void testGetScrollableUnitIncrementWithInvalidOrientation() {
+        assertThrows(IllegalArgumentException.class, () -> table.getScrollableUnitIncrement(visibleRectangle, -11, 0));
+
+    }
+}
\ No newline at end of file
