From fd175d2918d0234581e84c754639eb431e188673 Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Wed, 6 Mar 2024 14:51:25 +0200 Subject: [PATCH 1/7] Add autoscroll and preferred width --- bin/jmeter.properties | 6 ++++++ .../jmeter/visualizers/ViewResultsFullVisualizer.java | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index 24a6798e4c0..bacd9f14b3e 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1217,6 +1217,12 @@ view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsBoundar # Set to 0 to store all results (might consume a lot of memory) #view.results.tree.max_results=500 +# Set to true to auto-enable the checkbox for auto-scroll when samplers are received +#view.results.tree.autoscroll=false + +# default min width of the tree view +#view.results.tree.width=250 + # Maximum size of Document that can be parsed by Tika engine; default=10 * 1024 * 1024 (10 MB) # Set to 0 to disable the size check #document.max_size=0 diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index 44216aa7115..63c29774106 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -117,6 +117,12 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private static final String VIEWERS_ORDER = JMeterUtils.getPropDefault("view.results.tree.renderers_order", ""); // $NON-NLS-1$ //$NON-NLS-2$ + //default scroll checkbox status + private static final boolean SCROLL_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autoscroll", false); + + // default tree view width + private static final int VIEWERS_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 250); // $NON-NLS-1$ + private static final int REFRESH_PERIOD = JMeterUtils.getPropDefault("jmeter.gui.refresh_period", 500); private static final ImageIcon imageSuccess = JMeterUtils.getImage( @@ -431,13 +437,13 @@ private synchronized Component createLeftPanel() { jTree.setRootVisible(false); jTree.setShowsRootHandles(true); JScrollPane treePane = new JScrollPane(jTree); - treePane.setPreferredSize(new Dimension(200, 300)); + treePane.setPreferredSize(new Dimension(VIEWERS_WIDTH, 300)); VerticalPanel leftPane = new VerticalPanel(); leftPane.add(treePane, BorderLayout.CENTER); leftPane.add(createComboRender(), BorderLayout.NORTH); autoScrollCB = new JCheckBox(JMeterUtils.getResString("view_results_autoscroll")); // $NON-NLS-1$ - autoScrollCB.setSelected(false); + autoScrollCB.setSelected(SCROLL_CHECKBOX); autoScrollCB.addItemListener(this); leftPane.add(autoScrollCB, BorderLayout.SOUTH); return leftPane; From 955d7e2a06e153102695a095f8d3d5244a224373 Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Wed, 6 Mar 2024 15:19:27 +0200 Subject: [PATCH 2/7] Document the new configurable parameters --- bin/jmeter.properties | 4 ++-- .../jmeter/visualizers/ViewResultsFullVisualizer.java | 6 +++--- xdocs/usermanual/properties_reference.xml | 8 ++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index bacd9f14b3e..c3c845c6e63 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1217,10 +1217,10 @@ view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsBoundar # Set to 0 to store all results (might consume a lot of memory) #view.results.tree.max_results=500 -# Set to true to auto-enable the checkbox for auto-scroll when samplers are received +# Set to true to enable by default the checkbox for 'Scroll automatically?'. #view.results.tree.autoscroll=false -# default min width of the tree view +# Default width of the scroll view #view.results.tree.width=250 # Maximum size of Document that can be parsed by Tika engine; default=10 * 1024 * 1024 (10 MB) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index 63c29774106..9db807e818b 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -120,8 +120,8 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer //default scroll checkbox status private static final boolean SCROLL_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autoscroll", false); - // default tree view width - private static final int VIEWERS_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 250); // $NON-NLS-1$ + // default tree scroll width + private static final int SCROLL_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 250); // $NON-NLS-1$ private static final int REFRESH_PERIOD = JMeterUtils.getPropDefault("jmeter.gui.refresh_period", 500); @@ -437,7 +437,7 @@ private synchronized Component createLeftPanel() { jTree.setRootVisible(false); jTree.setShowsRootHandles(true); JScrollPane treePane = new JScrollPane(jTree); - treePane.setPreferredSize(new Dimension(VIEWERS_WIDTH, 300)); + treePane.setPreferredSize(new Dimension(SCROLL_WIDTH, 300)); VerticalPanel leftPane = new VerticalPanel(); leftPane.add(treePane, BorderLayout.CENTER); diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index cb9cd3ba2cd..15ad86727ea 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1556,6 +1556,14 @@ JMETER-SERVER Can be switched off by setting the value to -1.
Defaults to: 10000 + + Set to true to enable by default the checkbox for 'Scroll automatically?'.
+ Defaults to: false +
+ + Default width of the scroll view.
+ Defaults to: 250 +
Maximum size (in bytes) of Document that can be parsed by Tika engine
Set to zero to disable the size check.
From 7dbd64c50925d46b2faa6a3cf78d881e4d666c7c Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:01:50 +0200 Subject: [PATCH 3/7] Add Sampler name in Sampler Result tab --- .../org/apache/jmeter/visualizers/SamplerResultTab.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java index 7356f172295..da022ec157e 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java @@ -263,6 +263,10 @@ public void setupTabPane() { .append(JMeterUtils .getResString("view_results_thread_name")) //$NON-NLS-1$ .append(sampleResult.getThreadName()).append(NL); + statsBuff + .append(JMeterUtils + .getResString("view_results_sample_name")) //$NON-NLS-1$ + .append(sampleResult.getSampleLabel()).append(NL); String startTime = dateFormat .format(Instant.ofEpochMilli(sampleResult.getStartTime())); statsBuff @@ -369,6 +373,10 @@ public void setupTabPane() { resultModel.addRow(new RowResult( JMeterUtils.getParsedLabel("view_results_thread_name"), //$NON-NLS-1$ sampleResult.getThreadName())); + resultModel.addRow(new RowResult( + JMeterUtils.getParsedLabel( + "view_results_sample_name"), //$NON-NLS-1$ + sampleResult.getSampleLabel())); resultModel.addRow(new RowResult( JMeterUtils.getParsedLabel("view_results_sample_start"), //$NON-NLS-1$ startTime)); From 4ef8218b3d632b5c32162066400f7732c0be90b0 Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Thu, 9 Oct 2025 03:18:14 +0300 Subject: [PATCH 4/7] Add milliseconds and GMT/UTC timezone in sampler timestamp label; add checkbox to stop autoscroll on error; add button to focus listing on selected node. --- bin/jmeter.properties | 5 +- .../jmeter/visualizers/SamplerResultTab.java | 2 +- .../ViewResultsFullVisualizer.java | 117 ++++++++++++++++-- .../visualizers/gui/AbstractVisualizer.java | 8 +- .../jmeter/resources/messages.properties | 5 +- xdocs/usermanual/properties_reference.xml | 6 +- 6 files changed, 124 insertions(+), 19 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index ce1c152e25b..0a1e8a5be1e 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1217,9 +1217,12 @@ view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsBoundar # Set to 0 to store all results (might consume a lot of memory) #view.results.tree.max_results=500 -# Set to true to enable by default the checkbox for 'Scroll automatically?'. +# Set to true to enable by default the checkbox for auto scrolling. #view.results.tree.autoscroll=false +# Set to true to enable by default the checkbox for stop auto scrolling on 1st error. +#view.results.tree.autostop=true + # Default width of the scroll view #view.results.tree.width=250 diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java index 48837e42e3e..a83706812b6 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java @@ -87,7 +87,7 @@ public abstract class SamplerResultTab implements ResultRenderer { private static final Logger LOGGER = LoggerFactory.getLogger(SamplerResultTab.class); // N.B. these are not multi-threaded, so don't make it static private final DateTimeFormatter dateFormat = DateTimeFormatter - .ofPattern("yyyy-MM-dd HH:mm:ss z") // ISO format $NON-NLS-1$ + .ofPattern("yyyy-MM-dd HH:mm:ss.SSS O") // ISO format $NON-NLS-1$ .withZone(ZoneId.systemDefault()); private static final String NL = "\n"; // $NON-NLS-1$ diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index 674ba436864..b3c97201893 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -21,6 +21,8 @@ import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -43,8 +45,10 @@ import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.ImageIcon; +import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; @@ -120,6 +124,9 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer //default scroll checkbox status private static final boolean SCROLL_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autoscroll", false); + //default uncheck if failed scroll checkbox status + private static final boolean SCROLL_STOP_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autostop", true); + // default tree scroll width private static final int SCROLL_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 250); // $NON-NLS-1$ @@ -144,9 +151,10 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private ResultRenderer resultsRender = null; private Object resultsObject = null; private TreeSelectionEvent lastSelectionEvent; - private JCheckBox autoScrollCB; + private JCheckBox autoScrollCB, scrollStopCB; private final Queue buffer; private boolean dataChanged; + private SampleResult failedSampler; /** * Constructor @@ -169,6 +177,8 @@ public void add(final SampleResult sample) { synchronized (buffer) { buffer.add(sample); dataChanged = true; + if (!sample.isSuccessful() && failedSampler == null) + failedSampler = sample; } } @@ -176,6 +186,7 @@ public void add(final SampleResult sample) { * Update the visualizer with new data. */ private void updateGui() { + int failedSamplerPosition = 0; TreePath selectedPath = null; Object oldSelectedElement; Set oldExpandedElements; @@ -190,20 +201,19 @@ private void updateGui() { oldSelectedElement = getSelectedObject(); root.removeAllChildren(); for (SampleResult sampler: buffer) { - SampleResult res = sampler; // Add sample - DefaultMutableTreeNode currNode = new SearchableTreeNode(res, treeModel); + DefaultMutableTreeNode currNode = new SearchableTreeNode(sampler, treeModel); treeModel.insertNodeInto(currNode, root, root.getChildCount()); List path = new ArrayList<>(Arrays.asList(root, currNode)); selectedPath = checkExpandedOrSelected(path, - res, oldSelectedElement, + sampler, oldSelectedElement, oldExpandedElements, newExpandedPaths, selectedPath); - TreePath potentialSelection = addSubResults(currNode, res, path, oldSelectedElement, oldExpandedElements, newExpandedPaths); + TreePath potentialSelection = addSubResults(currNode, sampler, path, oldSelectedElement, oldExpandedElements, newExpandedPaths); if (potentialSelection != null) { selectedPath = potentialSelection; } // Add any assertion that failed as children of the sample node - AssertionResult[] assertionResults = res.getAssertionResults(); + AssertionResult[] assertionResults = sampler.getAssertionResults(); int assertionIndex = currNode.getChildCount(); for (AssertionResult assertionResult : assertionResults) { if (assertionResult.isFailure() || assertionResult.isError()) { @@ -215,6 +225,9 @@ private void updateGui() { assertionNode); } } + + if (sampler == failedSampler) + failedSamplerPosition = root.getChildCount() - 1; } treeModel.nodeStructureChanged(root); dataChanged = false; @@ -227,10 +240,14 @@ private void updateGui() { if (selectedPath != null) { jTree.setSelectionPath(selectedPath); } + if (autoScrollCB.isSelected() && root.getChildCount() > 1) { - jTree.scrollPathToVisible(new TreePath(new Object[] { root, - treeModel.getChild(root, root.getChildCount() - 1) })); + int pos = (scrollStopCB.isSelected() && failedSampler != null) ? failedSamplerPosition : root.getChildCount() - 1; + jTree.scrollPathToVisible(new TreePath(new Object[] { root, treeModel.getChild(root, pos) })); } + //if session not running, reset the error reference + if (!JMeterUtils.isTestRunning()) + failedSampler = null; } private Object getSelectedObject() { @@ -336,6 +353,7 @@ public void clearData() { } resultsRender.clearData(); resultsObject = null; + failedSampler = null; } /** {@inheritDoc} */ @@ -365,7 +383,7 @@ private void init() { // WARNING: called from ctor so must not be overridden (i searchAndMainSP.setOneTouchExpandable(true); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makeTitlePanel(), searchAndMainSP); splitPane.setOneTouchExpandable(true); - splitPane.setBorder(BorderFactory.createEmptyBorder()); + splitPane.setBorder(null); add(splitPane); // init right side with first render @@ -398,6 +416,44 @@ private void valueChanged(TreeSelectionEvent e, boolean forceRendering) { } Object userObject = node.getUserObject(); resultsRender.setSamplerResult(userObject); + + // Add Show Current Node button to the tab pane + if (rightSide.getTabCount() > 0) { + Component firstTab = rightSide.getComponentAt(0); + if (firstTab instanceof JPanel) { + JPanel samplerResultTab = (JPanel) firstTab; + // Add button at the top of the sampler result panel + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + JButton nodeInfoButton = new JButton(JMeterUtils.getResString("show_current_node")); // $NON-NLS-1$ + nodeInfoButton.addActionListener(e2 -> { + // Get the currently selected node when button is clicked + DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent(); + if (currentNode != null) { + TreePath path = new TreePath(currentNode.getPath()); + // First expand the path to make sure all parent nodes are visible + jTree.expandPath(path); + // Get the bounds before scrolling + Rectangle bounds = jTree.getPathBounds(path); + if (bounds != null) { + // Get the visible rectangle + Rectangle visible = jTree.getVisibleRect(); + // Calculate the new viewport position to center the node + int centerY = Math.max(0, bounds.y - (visible.height - bounds.height) / 2); + // Create rectangle that will center the node + Rectangle scrollTo = new Rectangle(0, centerY, 1, visible.height); + jTree.scrollRectToVisible(scrollTo); + // Ensure the node is selected and visible + jTree.setSelectionPath(path); + jTree.repaint(); + } + } + }); + buttonPanel.add(nodeInfoButton); + samplerResultTab.add(buttonPanel, BorderLayout.NORTH); + samplerResultTab.revalidate(); + } + } + resultsRender.setupTabPane(); // Processes Assertions // display a SampleResult if (userObject instanceof SampleResult) { @@ -440,12 +496,39 @@ private synchronized Component createLeftPanel() { treePane.setPreferredSize(new Dimension(SCROLL_WIDTH, 300)); VerticalPanel leftPane = new VerticalPanel(); - leftPane.add(treePane, BorderLayout.CENTER); - leftPane.add(createComboRender(), BorderLayout.NORTH); + + // Add controls panel at the top + JPanel controlsPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + controlsPane.add(createComboRender()); + leftPane.add(controlsPane, BorderLayout.NORTH); + + // Add tree panel in the center with proper sizing + JPanel treePanel = new JPanel(new BorderLayout()); + treePanel.add(treePane, BorderLayout.CENTER); + leftPane.add(treePanel, BorderLayout.CENTER); + + // Create bottom panel with checkbox + JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + + // Add autoscroll checkbox autoScrollCB = new JCheckBox(JMeterUtils.getResString("view_results_autoscroll")); // $NON-NLS-1$ autoScrollCB.setSelected(SCROLL_CHECKBOX); autoScrollCB.addItemListener(this); - leftPane.add(autoScrollCB, BorderLayout.SOUTH); + bottomPanel.add(autoScrollCB); + + // Add autoscroll checkbox + scrollStopCB = new JCheckBox(JMeterUtils.getResString("view_results_autostop")); // $NON-NLS-1$ + scrollStopCB.setSelected(SCROLL_STOP_CHECKBOX); + scrollStopCB.addItemListener(this); + bottomPanel.add(scrollStopCB); + autoScrollCB.doClick(); // to set the initial state of scrollStopCB + + leftPane.add(bottomPanel, BorderLayout.SOUTH); + + // Ensure the left pane maintains its size during window resizing + leftPane.setMinimumSize(new Dimension(SCROLL_WIDTH, 0)); + leftPane.setPreferredSize(new Dimension(SCROLL_WIDTH, 0)); + return leftPane; } @@ -622,6 +705,14 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, */ @Override public void itemStateChanged(ItemEvent e) { - // NOOP state is held by component + Object source = e.getItemSelectable(); + if (source == autoScrollCB) { + scrollStopCB.setEnabled(autoScrollCB.isSelected()); + } + } + + @Override + public String[] getFileExts() { + return new String[] { ".jtl" }; } } diff --git a/src/core/src/main/java/org/apache/jmeter/visualizers/gui/AbstractVisualizer.java b/src/core/src/main/java/org/apache/jmeter/visualizers/gui/AbstractVisualizer.java index 68802c6723d..0b463cd48e0 100644 --- a/src/core/src/main/java/org/apache/jmeter/visualizers/gui/AbstractVisualizer.java +++ b/src/core/src/main/java/org/apache/jmeter/visualizers/gui/AbstractVisualizer.java @@ -104,7 +104,7 @@ public abstract class AbstractVisualizer /** Logging. */ private static final Logger log = LoggerFactory.getLogger(AbstractVisualizer.class); - /** File Extensions */ + /** Default File Extensions */ private static final String[] EXTS = { ".xml", ".jtl", ".csv" }; // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ /** A panel allowing results to be saved. */ @@ -150,7 +150,7 @@ public void actionPerformed(ActionEvent e) { d.setVisible(true); }); - filePanel = new FilePanel(JMeterUtils.getResString("file_visualizer_output_file"), EXTS); // $NON-NLS-1$ + filePanel = new FilePanel(JMeterUtils.getResString("file_visualizer_output_file"), getFileExts()); // $NON-NLS-1$ filePanel.addChangeListener(this); filePanel.add(new JLabel(JMeterUtils.getResString("log_only"))); // $NON-NLS-1$ filePanel.add(errorLogging); @@ -346,4 +346,8 @@ public void clearGui(){ super.clearGui(); filePanel.clearGui(); } + + public String[] getFileExts() { + return EXTS; + } } diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties index 23721c4b4c9..8d146e06914 100644 --- a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties +++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties @@ -1401,7 +1401,8 @@ view_graph_tree_title=View Graph Tree view_results_assertion_error=Assertion error: view_results_assertion_failure=Assertion failure: view_results_assertion_failure_message=Assertion failure message: -view_results_autoscroll=Scroll automatically? +view_results_autoscroll=Auto scroll +view_results_autostop=Stop scroll on error view_results_childsamples=Child samples? view_results_datatype=Data type ("text"|"bin"|""): view_results_desc=Shows the text results of sampling in tree form @@ -1461,6 +1462,7 @@ view_results_table_request_tab_raw=Raw view_results_table_result_tab_parsed=Parsed view_results_table_result_tab_raw=Raw view_results_thread_name=Thread Name: +view_results_sample_name=Sample label: view_results_title=View Results view_results_tree_title=View Results Tree warning=Warning! @@ -1545,3 +1547,4 @@ xpath2_extractor_match_number_failure=MatchNumber out of bonds \: you_must_enter_a_valid_number=You must enter a valid number zh_cn=Chinese (Simplified) zh_tw=Chinese (Traditional) +show_current_node=Focus on selected node diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index 78f7d410b2d..9a7e7e14133 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1557,9 +1557,13 @@ JMETER-SERVER Defaults to: 10000 - Set to true to enable by default the checkbox for 'Scroll automatically?'.
+ Set to true to enable by default the checkbox for auto scrolling.
Defaults to: false
+ + Set to true to enable by default the checkbox for stop auto scrolling on 1st error.
+ Defaults to: true +
Default width of the scroll view.
Defaults to: 250 From 007bf065abc0f04ab0485363194cba480497c457 Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Thu, 3 Sep 2026 18:32:31 +0300 Subject: [PATCH 5/7] Changed default value(s); enhancements after real life usage --- bin/jmeter.properties | 2 +- .../ViewResultsFullVisualizer.java | 39 ++++++++----------- .../jmeter/resources/messages.properties | 4 +- xdocs/usermanual/properties_reference.xml | 2 +- 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index 0a1e8a5be1e..a0a1c38f2c5 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1218,7 +1218,7 @@ view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsBoundar #view.results.tree.max_results=500 # Set to true to enable by default the checkbox for auto scrolling. -#view.results.tree.autoscroll=false +#view.results.tree.autoscroll=true # Set to true to enable by default the checkbox for stop auto scrolling on 1st error. #view.results.tree.autostop=true diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index b3c97201893..7cb175246d8 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -122,7 +122,7 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer JMeterUtils.getPropDefault("view.results.tree.renderers_order", ""); // $NON-NLS-1$ //$NON-NLS-2$ //default scroll checkbox status - private static final boolean SCROLL_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autoscroll", false); + private static final boolean SCROLL_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autoscroll", true); //default uncheck if failed scroll checkbox status private static final boolean SCROLL_STOP_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autostop", true); @@ -154,7 +154,6 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private JCheckBox autoScrollCB, scrollStopCB; private final Queue buffer; private boolean dataChanged; - private SampleResult failedSampler; /** * Constructor @@ -177,8 +176,10 @@ public void add(final SampleResult sample) { synchronized (buffer) { buffer.add(sample); dataChanged = true; - if (!sample.isSuccessful() && failedSampler == null) - failedSampler = sample; + if (!"true".equals(System.getProperty("java.awt.headless"))) { + if (!sample.isSuccessful() && autoScrollCB.isSelected() && scrollStopCB.isSelected()) + autoScrollCB.setSelected(false); + } } } @@ -186,7 +187,6 @@ public void add(final SampleResult sample) { * Update the visualizer with new data. */ private void updateGui() { - int failedSamplerPosition = 0; TreePath selectedPath = null; Object oldSelectedElement; Set oldExpandedElements; @@ -201,19 +201,20 @@ private void updateGui() { oldSelectedElement = getSelectedObject(); root.removeAllChildren(); for (SampleResult sampler: buffer) { + SampleResult res = sampler; // Add sample - DefaultMutableTreeNode currNode = new SearchableTreeNode(sampler, treeModel); + DefaultMutableTreeNode currNode = new SearchableTreeNode(res, treeModel); treeModel.insertNodeInto(currNode, root, root.getChildCount()); List path = new ArrayList<>(Arrays.asList(root, currNode)); selectedPath = checkExpandedOrSelected(path, - sampler, oldSelectedElement, + res, oldSelectedElement, oldExpandedElements, newExpandedPaths, selectedPath); - TreePath potentialSelection = addSubResults(currNode, sampler, path, oldSelectedElement, oldExpandedElements, newExpandedPaths); + TreePath potentialSelection = addSubResults(currNode, res, path, oldSelectedElement, oldExpandedElements, newExpandedPaths); if (potentialSelection != null) { selectedPath = potentialSelection; } // Add any assertion that failed as children of the sample node - AssertionResult[] assertionResults = sampler.getAssertionResults(); + AssertionResult[] assertionResults = res.getAssertionResults(); int assertionIndex = currNode.getChildCount(); for (AssertionResult assertionResult : assertionResults) { if (assertionResult.isFailure() || assertionResult.isError()) { @@ -226,8 +227,6 @@ private void updateGui() { } } - if (sampler == failedSampler) - failedSamplerPosition = root.getChildCount() - 1; } treeModel.nodeStructureChanged(root); dataChanged = false; @@ -242,12 +241,9 @@ private void updateGui() { } if (autoScrollCB.isSelected() && root.getChildCount() > 1) { - int pos = (scrollStopCB.isSelected() && failedSampler != null) ? failedSamplerPosition : root.getChildCount() - 1; - jTree.scrollPathToVisible(new TreePath(new Object[] { root, treeModel.getChild(root, pos) })); + jTree.scrollPathToVisible(new TreePath(new Object[] { root, + treeModel.getChild(root, root.getChildCount() - 1) })); } - //if session not running, reset the error reference - if (!JMeterUtils.isTestRunning()) - failedSampler = null; } private Object getSelectedObject() { @@ -353,7 +349,8 @@ public void clearData() { } resultsRender.clearData(); resultsObject = null; - failedSampler = null; + autoScrollCB.setSelected(SCROLL_CHECKBOX); + scrollStopCB.setSelected(SCROLL_STOP_CHECKBOX); } /** {@inheritDoc} */ @@ -517,11 +514,10 @@ private synchronized Component createLeftPanel() { bottomPanel.add(autoScrollCB); // Add autoscroll checkbox - scrollStopCB = new JCheckBox(JMeterUtils.getResString("view_results_autostop")); // $NON-NLS-1$ + scrollStopCB = new JCheckBox(JMeterUtils.getResString("view_results_scrollstop")); // $NON-NLS-1$ scrollStopCB.setSelected(SCROLL_STOP_CHECKBOX); scrollStopCB.addItemListener(this); bottomPanel.add(scrollStopCB); - autoScrollCB.doClick(); // to set the initial state of scrollStopCB leftPane.add(bottomPanel, BorderLayout.SOUTH); @@ -705,10 +701,7 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, */ @Override public void itemStateChanged(ItemEvent e) { - Object source = e.getItemSelectable(); - if (source == autoScrollCB) { - scrollStopCB.setEnabled(autoScrollCB.isSelected()); - } + // NOOP state is held by component } @Override diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties index 8d146e06914..73499f26eb1 100644 --- a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties +++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties @@ -1401,8 +1401,8 @@ view_graph_tree_title=View Graph Tree view_results_assertion_error=Assertion error: view_results_assertion_failure=Assertion failure: view_results_assertion_failure_message=Assertion failure message: -view_results_autoscroll=Auto scroll -view_results_autostop=Stop scroll on error +view_results_autoscroll=Auto scroll? +view_results_autostop=Stop scroll on error? view_results_childsamples=Child samples? view_results_datatype=Data type ("text"|"bin"|""): view_results_desc=Shows the text results of sampling in tree form diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index 9a7e7e14133..7ed3c4f0b86 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1558,7 +1558,7 @@ JMETER-SERVER Set to true to enable by default the checkbox for auto scrolling.
- Defaults to: false + Defaults to: true
Set to true to enable by default the checkbox for stop auto scrolling on 1st error.
From 0ef4456af178c2d62109e5d259753d4c35dc5b1f Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Thu, 3 Sep 2026 19:56:14 +0300 Subject: [PATCH 6/7] Fix build failures --- .../jmeter/visualizers/ViewResultsFullVisualizer.java | 10 +++++----- .../org/apache/jmeter/resources/messages.properties | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index 35eade20795..fbe5dd21ae4 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -127,7 +127,7 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private static final boolean SCROLL_STOP_CHECKBOX = JMeterUtils.getPropDefault("view.results.tree.autostop", true); // default tree scroll width - private static final int SCROLL_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 250); // $NON-NLS-1$ + private static final int SCROLL_WIDTH = JMeterUtils.getPropDefault("view.results.tree.width", 300); // $NON-NLS-1$ private static final int REFRESH_PERIOD = JMeterUtils.getPropDefault("jmeter.gui.refresh_period", 500); @@ -175,8 +175,9 @@ public void add(final SampleResult sample) { buffer.add(sample); dataChanged = true; if (!"true".equals(System.getProperty("java.awt.headless"))) { - if (!sample.isSuccessful() && autoScrollCB.isSelected() && scrollStopCB.isSelected()) + if (!sample.isSuccessful() && autoScrollCB.isSelected() && scrollStopCB.isSelected()) { autoScrollCB.setSelected(false); + } } } } @@ -414,8 +415,8 @@ private void valueChanged(TreeSelectionEvent e, boolean forceRendering) { // Add Show Current Node button to the tab pane if (rightSide.getTabCount() > 0) { Component firstTab = rightSide.getComponentAt(0); - if (firstTab instanceof JPanel) { - JPanel samplerResultTab = (JPanel) firstTab; + if (firstTab instanceof JPanel samplerResultTab) { + samplerResultTab = (JPanel) firstTab; // Add button at the top of the sampler result panel JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); JButton nodeInfoButton = new JButton(JMeterUtils.getResString("show_current_node")); // $NON-NLS-1$ @@ -487,7 +488,6 @@ private synchronized Component createLeftPanel() { jTree.setRootVisible(false); jTree.setShowsRootHandles(true); JScrollPane treePane = new JScrollPane(jTree); - treePane.setPreferredSize(new Dimension(SCROLL_WIDTH, 300)); VerticalPanel leftPane = new VerticalPanel(); diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties index f8e3aa7db71..5233f87dca1 100644 --- a/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties +++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages.properties @@ -1401,8 +1401,8 @@ view_graph_tree_title=View Graph Tree view_results_assertion_error=Assertion error: view_results_assertion_failure=Assertion failure: view_results_assertion_failure_message=Assertion failure message: -view_results_autoscroll=Auto scroll? -view_results_autostop=Stop scroll on error? +view_results_autoscroll=Auto scroll +view_results_scrollstop=Stop scroll on error view_results_childsamples=Child samples? view_results_datatype=Data type ("text"|"bin"|""): view_results_desc=Shows the text results of sampling in tree form From befb348d68a075f9b3447260fbca3bcc5840efc2 Mon Sep 17 00:00:00 2001 From: KingRabbid <13966341+KingRabbid@users.noreply.github.com> Date: Thu, 3 Sep 2026 20:11:02 +0300 Subject: [PATCH 7/7] Fix new build failures --- .../apache/jmeter/visualizers/ViewResultsFullVisualizer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index fbe5dd21ae4..37fdc7ca1b7 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -150,7 +150,8 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private ResultRenderer resultsRender = null; private Object resultsObject = null; private TreeSelectionEvent lastSelectionEvent; - private JCheckBox autoScrollCB, scrollStopCB; + private JCheckBox autoScrollCB; + private JCheckBox scrollStopCB; private final Queue buffer = new ArrayDeque<>(); private final int maxResults; private boolean dataChanged;