liudianwu 发表于 2023-8-23 12:00:08

Qt/C++开发经验小技巧281-285

281. 悬停窗体QDockWidget默认在标题栏右键会弹出悬停模块的显示隐藏菜单,如果需要去掉,会发现设置Qt::NoContextMenu或者事件过滤器拦截都是无效的,必须设置 dockWidget->setContextMenuPolicy(Qt::PreventContextMenu); 。

282. Qt中的布局有个默认的margin边距值和spacing间距值,在没有设置该值的情况下,会根据运行的环境自动设置该值,比如1080P分辨率和2k分辨率的电脑,该值的默认值不一样,并不是你在UI设计的时候属性栏中看到的值,这个要特别注意,你看到的7可能在目标平台运行的时候是11,如果一定要按照你想要的值来运行,可以重新设置即可,设置过哪一个就该值按照设定的来。如果不想一个个设置调整布局中的间距边距,你需要用到万能**样式代理,继承QProxyStyle类然后重新设置样式即可。该方式也是属于斗皇级别的UI外观控制策略,最终所有的qss样式也是要通过该样式去绘制的,意味着这里你可以重新定义和控制所有控件的外观样式,非常的强大。
```cpp
//也可以继承Qt内置的样式比如 QFusionStyle/QCleanlooksStyle
class QCustomStyle : public QProxyStyle
{
public:
    int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const {

      if (metric == QStyle::PM_LayoutHorizontalSpacing || metric == QStyle::PM_LayoutVerticalSpacing) {
            //将布局中的横向和垂直间距设置成10
            return 10;
      } else if (metric == QStyle::PM_ButtonMargin) {
            //将所有按钮的margin边距设置成20
            return 20;
      }
      return QProxyStyle::pixelMetric(metric, option, widget);
    }
};

qApp->setStyle(new QCustomStyle);
```

283. 养成良好的编程习惯至关重要,尤其是对变量的初始化,包括一些类对象的定义后也务必记得初始化,否则在不初始化的时候,默认值飘忽不定,比如int默认值在debug/release下以及不同编译器下默认值都不一样,甚至在头文件定义以及函数中定义都可能不同的默认值,下面表格中整理的测试的值,对应的int值飘忽不定的。常见的默认初始化定义建议 int i = 0; bool b = false; class a = NULL;

|版本|定义位置|debug/release|int|bool|
|:------|:------|:------|:------|:------|
|Qt4.7/mingw|头文件|debug|7077464|true|
|Qt4.7/mingw|头文件|release|48|true|
|Qt4.7/mingw|函数中|debug|2162216|false|
|Qt4.7/mingw|函数中|release|0|false|
|Qt5.7/msvc|头文件|debug|-1|true|
|Qt5.7/msvc|头文件|release|-1|true|
|Qt5.7/msvc|函数中|debug|1898108572|false|
|Qt5.7/msvc|函数中|release|18872512|true|
|Qt6.5/mingw|头文件|debug|-1305540880|true|
|Qt6.5/mingw|头文件|release|-1124044992|true|
|Qt6.5/mingw|函数中|debug|0|false|
|Qt6.5/mingw|函数中|release|0|false|

284. 对QTableView进行全部选中、全部不选、反向选中操作。
```cpp
void frmXXX::initAction()
{
    QAction *actionAll = new QAction("全部选中");
    QAction *actionInvert = new QAction("反向选中");
    QAction *actionClear = new QAction("清空选中");
    connect(actionAll, SIGNAL(triggered(bool)), this, SLOT(doAction()));
    connect(actionInvert, SIGNAL(triggered(bool)), this, SLOT(doAction()));
    connect(actionClear, SIGNAL(triggered(bool)), this, SLOT(doAction()));

    ui->tableView->addAction(actionAll);
    ui->tableView->addAction(actionInvert);
    ui->tableView->addAction(actionClear);
    ui->tableView->setContextMenuPolicy(Qt::ActionsContextMenu);
}

void frmXXX::doAction()
{
    QAction *action = (QAction *)sender();
    QString text = action->text();
    if (text == "全部选中") {
      ui->tableView->selectAll();
    } else if (text == "反向选中") {
      //找到所有选中的行集合
      QList<int> rows;
      QModelIndexList list = ui->tableView->selectionModel()->selectedRows();
      int count = list.count();
      for (int i = 0; i < count; ++i) {
            rows << list.at(i).row();
      }

      //先清空所有选中
      ui->tableView->clearSelection();
      //不在选中行集合的则选中
      count = ui->tableView->model()->rowCount();
      for (int i = 0; i < count; ++i) {
            if (!rows.contains(i)) {
                ui->tableView->selectRow(i);
            }
      }
    } else if (text == "清空选中") {
      ui->tableView->clearSelection();
    }
}
```

285. pro文件中多重条件判断,前面 ! 表示非,中间 | 表示或(两个条件满足其一),中间 :: 表示与(两个条件都要满足)。
```cpp
//下面表示安卓或者ios平台
android|ios {}

//下面表示非安卓和ios平台
!android::!ios {}
```

国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)

页: [1]
查看完整版本: Qt/C++开发经验小技巧281-285