setViewportMargins() and “locked” rows and columns

2019-06-27 05:22发布

问题:

the documentation of void QAbstractScrollArea::setViewportMargins(int left, int top, int right, int bottom) says:

Sets the margins around the scrolling area to left, top, right and bottom. This is useful for applications such as spreadsheets with "locked" rows and columns. The marginal space is is left blank; put widgets in the unused area. Note that this function is frequently called by QTreeView and QTableView, so margins must be implemented by QAbstractScrollArea subclasses. Also, if the subclasses are to be used in item views, they should not call this function.

First of all, I got confused with description itself. The function is not virtual so it is not the case when I should re-implement it to supply my margins. If I should call it than when, at what points? And if QTreeView is calling it internally with its own values than how our calls will cooperate? Looking at Qt sources I have found that QTreeView::updateGeometries() does call it with parameters (essentially) 0, headerHeight, 0, 0. So should I re-implement updateGeometries()?

Googling further I found that other people call setViewportMargins() from overridden resizeEvent(). So I also did so and this works BUT:

  1. I am wondering how this technique co-exist with internal QTreeView::updateGeometries() that calls setViewportMargins() with essentially hard-coded parameters (only headerHeight is changed to 0 if header is hidden)?
  2. Although it works the "unused area" appears above header. But to implement "locked" rows mentioned by documentation one needs this area to be under header

I have got unused area below header by overriding updateGeometries() and moving header() to the top (after calling QTreeView::updateGeometries();). But I am not sure that this is right thing to do.

So my question is: What way to implement "locked" rows is meant by setViewportMargins() documentation and how should they actually be implemented?

Note that I am aware about another way to implement frozen rows (or columns) - Frozen Column Example. But this is not exactly what I need because this technique hides first row(column) of main table(tree) widget and shows it in overlay (static) widget. In my case I need a different info in the area below header and main widget should be actually moved down to show all rows

回答1:

Actually that's very good question. Personally I dont think that setViewportMargins() is a way to go. By playing with viewportMargins only thing you can achieve is to 'shift' borders of where QTableView will draw attached model and then you have to deal with empty spaces around by drawing 'frozen' rows etc. Making those empty spaces 'owner-draw' you should always look for grid style, fonts size etc of the 'main grid' to make your 'frozen' rows/columns looks the same as main grid.

I tried several approaches to make it decently nice and convenient to write code around. At the end I end up with making widget which combines main grid (no headers), top and left grids WITH headers + corner widget. By doing that I've got pretty straight way to handle frozen parts with model filters on top of a main grid model as well as easy way to have splitters for 'frozen' parts etc..