Repository: vispy/vispy

Issue:
axis labels problem
I was using the plot.py example and I got the following problems:
1. the xaxis labels are overlapped to the x axis
2. the xaxis labels values do not correspond to the actual x axis domain; they are adjusted to the correct values after resizing the window.
3. some other problems with yaxis labels and title (see attached picture)

![plot_py_screenshot](https://user-images.githubusercontent.com/50824984/68126482-34191a80-ff14-11e9-9690-9885c0ddc735.JPG)



Discussion:
Some of this seems like the default font size is too large. We've seen the ticks not updating issue before, but I thought we fixed it. What backend are you using?
Here is what it looks like with the current master branch on my Ubuntu system with PyQt5:

![image](https://user-images.githubusercontent.com/1828519/68128912-3ceef980-fede-11e9-9442-3f34bbb2685c.png)

I am using PyQt5 on Windows 10. Yes there is also a font size problem. It would be better if the axis_font_size and the tick_font_size could be set from the user application. 
Your plot is better than mine, but, as you can see, the x axis labels are wrong (they should be from 0 to 10) and they touch the tick marks.
You're right about the ticks being wrong. I guess this is still an issue.

The tick labels touching the tick marks may be something that has always existed and was never completely made to look "perfect". @larsoner may remember more.
I could get a better plot modifying the font size of the labels and adding some margins.

![plot_py_screenshot2](https://user-images.githubusercontent.com/50824984/68214527-e963d500-ffdd-11e9-901a-fce005734eed.jpg)


```fig[0,0].xlabel._text_visual.font_size=8
fig[0,0].ylabel._text_visual.font_size=8
fig[0,0].ylabel.width_min = fig[0,0].ylabel.width_max = 80
fig[0,0].title._text_visual.font_size=8
fig[0,0].xaxis.axis.tick_label_margin=35
fig[0,0].yaxis.axis.axis_label_margin=50



As I noticed that if you move the plot the xaxis is updated with the correct tick labels, I was trying to force an xaxis update setting _need_update=True and calling the update() method, but it didn't work. 

```
fig[0,0].xaxis.axis._need_update = True
fig[0,0].xaxis.axis.update()
```

If I remember correctly, the last time this came up it was caused by a race condition where the ticks would be updated to the correct values and then immediately set back to the incorrect (initial) values. I'm sorry I don't have time to look in to it more right now.
Thank you for the link to the bug fixes related to AxisVisual. They seem to concern some other problems.
In my Qt application I found that the x axis domain is correct until the show() method is called. After, it gets wrong. If I update the plot after the show() method is executed, the x axis domain is correct.
Something happens while executing the show() method. 
A strange thing is that only the x axis has this kind of problems.
Yeah, I think I've tried to fix this bug in the past, but never found the real problem or maybe it was that it didn't have an easy solution. Like I mentioned I think it has to do with a basic default x range being set *after* the real data's x range is already set. Solving this bug will require walking through the code and finding when the domain is updated and from where (is it a default value, is it from the data, did the user set it, etc). I won't have time to look in to this any time soon though.
This is the code

```
        print('(plot-1) xaxis domain:', self.plot.ax.xaxis.axis.domain)
        print('(plot-1) yaxis domain:', self.plot.ax.yaxis.axis.domain)
       
        self.show()
        
        print('(plot-2) xaxis domain:', self.plot.ax.xaxis.axis.domain)
        print('(plot-2) yaxis domain:', self.plot.ax.yaxis.axis.domain)
        
        self.plot.update_view()
        
        print('(plot-3) xaxis domain:', self.plot.ax.xaxis.axis.domain)
        print('(plot-3) yaxis domain:', self.plot.ax.yaxis.axis.domain)
```

This is the output:

```
(plot-1) xaxis domain: (-3.435610274790101, 3.098064060261222)
(plot-1) yaxis domain: (-0.8999991856813033, 18.900001782059757)
(plot-2) xaxis domain: (-5.046775266898924, -4.957760627687946)
(plot-2) yaxis domain: (-0.8999998271748488, 18.900000467268093)
(plot-3) xaxis domain: (-3.435610297180214, 3.0980642209056075)
(plot-3) yaxis domain: (-0.8999998271748488, 18.900000467268093)
```
The plot-2 x axis domain is the wrong one.
The solution I found for my application is not so elegant, but I am satisfied with it. The user will not see the bug anyway.

Resolving patch:
diff --git a/vispy/plot/plotwidget.py b/vispy/plot/plotwidget.py
--- a/vispy/plot/plotwidget.py
+++ b/vispy/plot/plotwidget.py
@@ -122,14 +122,6 @@ def _configure_2d(self, fg_color=None):
         yaxis_widget = self.grid.add_widget(self.yaxis, row=2, col=3)
         yaxis_widget.width_max = 40
 
-        self.view = self.grid.add_view(row=2, col=4,
-                                       border_color='grey', bgcolor="#efefef")
-        self.view.camera = 'panzoom'
-        self.camera = self.view.camera
-
-        self.cbar_right = self.grid.add_widget(None, row=2, col=5)
-        self.cbar_right.width_max = 1
-
         # row 3
         # xaxis - column 4
         self.xaxis = scene.AxisWidget(orientation='bottom', text_color=fg,
@@ -137,6 +129,9 @@ def _configure_2d(self, fg_color=None):
         xaxis_widget = self.grid.add_widget(self.xaxis, row=3, col=4)
         xaxis_widget.height_max = 40
 
+        self.cbar_right = self.grid.add_widget(None, row=2, col=5)
+        self.cbar_right.width_max = 1
+
         # row 4
         # xlabel - column 4
         self.xlabel = scene.Label("")
@@ -147,6 +142,12 @@ def _configure_2d(self, fg_color=None):
         self.cbar_bottom = self.grid.add_widget(None, row=5, col=4)
         self.cbar_bottom.height_max = 1
 
+        # This needs to be added to the grid last (to fix #1742)
+        self.view = self.grid.add_view(row=2, col=4,
+                                       border_color='grey', bgcolor="#efefef")
+        self.view.camera = 'panzoom'
+        self.camera = self.view.camera
+
         self._configured = True
         self.xaxis.link_view(self.view)
         self.yaxis.link_view(self.view)


Test patch:
diff --git a/vispy/plot/tests/test_plot.py b/vispy/plot/tests/test_plot.py
--- a/vispy/plot/tests/test_plot.py
+++ b/vispy/plot/tests/test_plot.py
@@ -5,6 +5,12 @@
 import vispy.plot as vp
 from vispy.testing import (assert_raises, requires_application,
                            run_tests_if_main)
+from vispy.visuals.axis import AxisVisual
+
+try:
+    from unittest import mock
+except ImportError:
+    import mock
 
 
 @requires_application()
@@ -18,4 +24,28 @@ def test_figure_creation():
         # collision
         assert_raises(ValueError, fig.__getitem__, (slice(1, 3), 1))
 
+
+@requires_application()
+def test_plot_widget_axes():
+    """Test that the axes domains are updated correctly when a figure is first drawn"""
+
+    fig = vp.Fig(size=(800, 800), show=False)
+    point = (0, 100)
+    fig[0, 0].plot((point, point))
+    # mocking the AxisVisual domain.setter
+    domain_setter = mock.Mock(wraps=AxisVisual.domain.fset)
+    mock_property = AxisVisual.domain.setter(domain_setter)
+
+    with mock.patch.object(AxisVisual, "domain", mock_property):
+        # note: fig.show() must be called for this test to work... otherwise
+        # Grid._update_child_widget_dim is not triggered and the axes aren't updated
+        fig.show(run=False)
+        # currently, the AxisWidget adds a buffer of 5% of the 
+        # full range to either end of the axis domain
+        buffer = (point[1] - point[0]) * 0.05
+        expectation = [point[0] - buffer, point[1] + buffer]
+        for call in domain_setter.call_args_list:
+            assert [round(x, 2) for x in call[0][1]] == expectation
+
+
 run_tests_if_main()