Как моделировать битовые поля в записях Delphi?

Вторая проблема вызвана тем, что прямоугольник, который вы получаете из drawBackground, относится к сцене, а не к области просмотра, поэтому решение состоит в том, чтобы скопировать этот прямоугольник и установить высоту:

class MyScene(QGraphicsScene):
    def drawBackground(self, painter, rect):
        bg_brush = QBrush(QColor(255, 255, 255), Qt.SolidPattern)
        painter.fillRect(rect, bg_brush)
        #Red bar on top
        painter.setPen(QPen(Qt.NoPen))
        brush = QBrush(QColor(139, 0, 0), Qt.SolidPattern)
        r = QRectF(rect)
        r.setY(0)
        r.setHeight(30)
        painter.fillRect(r, brush)

Все еще работаем над Первая проблема ...

Полное решение:

Я учел ваш код, поскольку есть много повторяющихся вещей, но главной задачей было реализовать метод Adjust_scene, который вычисляет область просмотра с использованием itemsBoundingRect () и области просмотра. Хитрость заключается в том, чтобы вызывать эту функцию через мгновение после установки нового QGraphicsWidget, также хорошо вызывать ее в resizeEvent QGraphicsView.

from PySide2 import QtCore, QtGui, QtWidgets

class PixmapItem(QtWidgets.QGraphicsWidget):
    def __init__(self, image, parent=None):
        super(PixmapItem, self).__init__(parent)
        self.pic = QtGui.QPixmap(image)

    def boundingRect(self):
        return QtCore.QRectF(self.pic.rect())

    def sizeHint(self, which, constraint=QtCore.QSizeF()):
        return self.boundingRect().size()

    def paint(self, painter, option, widget):
        painter.drawPixmap(QtCore.QPoint(), self.pic)

class GraphicsScene(QtWidgets.QGraphicsScene):
    def drawBackground(self, painter, rect):
        bg_brush = QtGui.QBrush(QtGui.QColor(255, 255, 255), QtCore.Qt.SolidPattern)
        painter.fillRect(rect, bg_brush)
        #Red bar on top
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        brush = QtGui.QBrush(QtGui.QColor(139, 0, 0), QtCore.Qt.SolidPattern)
        r = QtCore.QRectF(rect)
        r.setY(0)
        r.setHeight(30)
        painter.fillRect(r, brush)

class GraphicsView(QtWidgets.QGraphicsView):
    def adjust_scene(self):
        if self.scene() is None: return
        r = self.scene().itemsBoundingRect()
        view_rect = self.mapToScene(self.viewport().rect()).boundingRect()
        w = max(r.size().width(), view_rect.size().width())
        h = max(r.size().height(), view_rect.size().height())
        self.scene().setSceneRect(QtCore.QRectF(QtCore.QPointF(), QtCore.QSizeF(w, h)))

    def resizeEvent(self, event):
        super(GraphicsView, self).resizeEvent(event)
        self.adjust_scene()

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.load_button = QtWidgets.QPushButton(text="Load")
        self.load_button.clicked.connect(self.load)
        self.column_spinbox = QtWidgets.QSpinBox(
            value=4,
            minimum=1,
            maximum=25,
            enabled=False
        )
        self.column_spinbox.valueChanged[int].connect(self.set_columns)
        self.scene = GraphicsScene()
        self.view = GraphicsView(self.scene)
        lay = QtWidgets.QVBoxLayout(self)
        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(self.load_button)
        hlay.addWidget(self.column_spinbox)
        lay.addLayout(hlay)
        lay.addWidget(self.view)

    @QtCore.Slot()
    def load(self):
        self.imglist = ["py.png", "py.png","py.png","py.png","py.png","py.png",
            "py.png","py.png","py.png","py.png","py.png","py.png"]
        self.set_columns(self.column_spinbox.value())
        self.column_spinbox.setEnabled(True)

    @QtCore.Slot(int)
    def set_columns(self, column):
        self.view.scene().clear()
        item = self.scene.addText("Some Sample Text.", QtGui.QFont("Arial", 16, QtGui.QFont.Light))
        item.setDefaultTextColor(QtGui.QColor(255, 255, 255))

        top = item.mapToScene(item.boundingRect().bottomLeft())
        self.graphics_widget = QtWidgets.QGraphicsWidget()
        graphics_layout = QtWidgets.QGraphicsGridLayout(self.graphics_widget)
        self.view.scene().addItem(self.graphics_widget)
        self.graphics_widget.setPos(top)

        for i, img in enumerate(self.imglist):
            item = PixmapItem(img)
            row, col = divmod(i, column)
            graphics_layout.addItem(item, row, col)
            graphics_layout.setColumnSpacing(column, 15)
            graphics_layout.setRowSpacing(row, 15)
        QtCore.QTimer.singleShot(0, self.view.adjust_scene)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

enter image description here

enter image description here [118 ]

enter image description here

25
задан PatrickvL 11 November 2008 в 20:50
поделиться

4 ответа

Спасибо все!

На основе этой информации я уменьшил это до:

RBits = record
public
  BaseMid: BYTE;
private
  Flags: WORD;
  function GetBits(const aIndex: Integer): Integer;
  procedure SetBits(const aIndex: Integer; const aValue: Integer);
public
  BaseHi: BYTE;
  property _Type: Integer index $0005 read GetBits write SetBits; // 5 bits at offset 0
  property Dpl: Integer index $0502 read GetBits write SetBits; // 2 bits at offset 5
  property Pres: Integer index $0701 read GetBits write SetBits; // 1 bit at offset 7
  property LimitHi: Integer index $0804 read GetBits write SetBits; // 4 bits at offset 8
  property Sys: Integer index $0C01 read GetBits write SetBits; // 1 bit at offset 12
  property Reserved_0: Integer index $0D01 read GetBits write SetBits; // 1 bit at offset 13
  property Default_Big: Integer index $0E01 read GetBits write SetBits; // 1 bit at offset 14
  property Granularity: Integer index $0F01 read GetBits write SetBits; // 1 bit at offset 15
end;

Индекс кодируется следующим образом: (BitOffset shl 8) + NrBits. Где 1 <=NrBits <=32 и 0 <=BitOffset <=31

Теперь, я могу получить и установить эти биты следующим образом:

{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
function RBits.GetBits(const aIndex: Integer): Integer;
var
  Offset: Integer;
  NrBits: Integer;
  Mask: Integer;
begin
  NrBits := aIndex and $FF;
  Offset := aIndex shr 8;

  Mask := ((1 shl NrBits) - 1);

  Result := (Flags shr Offset) and Mask;
end;

procedure RBits.SetBits(const aIndex: Integer; const aValue: Integer);
var
  Offset: Integer;
  NrBits: Integer;
  Mask: Integer;
begin
  NrBits := aIndex and $FF;
  Offset := aIndex shr 8;

  Mask := ((1 shl NrBits) - 1);
  Assert(aValue <= Mask);

  Flags := (Flags and (not (Mask shl Offset))) or (aValue shl Offset);
end;

Довольно изящный, разве Вы не думаете?!?!

PS: Rudy Velthuis теперь включал исправленную версию этого в его превосходных "Ловушках преобразования" - статья.

29
ответ дан 28 November 2019 в 20:52
поделиться

Угол Дельфи Rudy является лучшим ресурсом, который я знаю оценки совместимость C/C++ и Дельфи. Его Ловушки преобразования в значительной степени, необходимость читала при использовании API C/C++ в Дельфи. Глава, которой Вы будете больше всего интересоваться, Записи и выравнивание-> Битовые поля , но я убеждаю Вас считать всю вещь, от начала до конца, дважды . Другие статьи определенно стоят инвестиций времени, также.

15
ответ дан 28 November 2019 в 20:52
поделиться

Хорошо, моя побитовая обработка немного ржава, таким образом, я, возможно, инвертировал байты. Но код ниже дает общее представление:

type
  TBits = record
  private
    FBaseMid     : Byte;
    FTypeDplPres :  Byte;
    FLimitHiSysEa: Byte;
    FBaseHi      : Byte;

    function GetType: Byte;
    procedure SetType(const AType: Byte);
    function GetDpl: Byte;
    procedure SetDbl(const ADpl: Byte);
    function GetBit1(const AIndex: Integer): Boolean;
    procedure SetBit1(const AIndex: Integer; const AValue: Boolean);
    function GetLimitHi: Byte;
    procedure SetLimitHi(const AValue: Byte);
    function GetBit2(const AIndex: Integer): Boolean;
    procedure SetBit2(const AIndex: Integer; const AValue: Boolean);

  public
    property BaseMid: Byte read FBaseMid write FBaseMid;
    property &Type: Byte read GetType write SetType; // 0..31
    property Dpl: Byte read GetDpl write SetDbl; // 0..3
    property Pres: Boolean index 128 read GetBit1 write SetBit1; 
    property LimitHi: Byte read GetLimitHi write SetLimitHi; // 0..15

    property Sys: Boolean index 16 read GetBit2 write SetBit2; 
    property Reserved0: Boolean index 32 read GetBit2 write SetBit2; 
    property DefaultBig: Boolean index 64 read GetBit2 write SetBit2; 
    property Granularity: Boolean index 128 read GetBit2 write SetBit2; 
    property BaseHi: Byte read FBaseHi write FBaseHi;
  end;

  function TBits.GetType: Byte;
  begin
    Result := (FTypeDplPres shr 3) and $1F;
  end;

  procedure TBits.SetType(const AType: Byte);
  begin
    FTypeDplPres := (FTypeDplPres and $07) + ((AType and $1F) shr 3);
  end;

  function TBits.GetDpl: Byte;
  begin
    Result := (FTypeDplPres and $06) shr 1;
  end;

  procedure TBits.SetDbl(const ADpl: Byte);
  begin
    FTypeDblPres := (FTypeDblPres and $F9) + ((ADpl and $3) shl 1);
  end;

  function TBits.GetBit1(const AIndex: Integer): Boolean;
  begin
    Result := FTypeDplPres and AIndex = AIndex;
  end;

  procedure TBits.SetBit1(const AIndex: Integer; const AValue: Boolean);
  begin
    if AValue then
      FTypeDblPres := FTypeDblPres or AIndex
    else
      FTypeDblPres := FTypeDblPres and not AIndex;
  end;

  function TBits.GetLimitHi: Byte;
  begin
    Result := (FLimitHiSysEa shr 4) and $0F;
  end;

  procedure TBits.SetLimitHi(const AValue: Byte);
  begin
    FLimitHiSysEa := (FLimitHiSysEa and $0F) + ((AValue and $0F) shr 4);
  end;

  function TBits.GetBit2(const AIndex: Integer): Boolean;
  begin
    Result := FLimitHiSysEa and AIndex = AIndex;
  end;

  procedure TBits.SetBit2(const AIndex: Integer; const AValue: Boolean);
  begin
    if AValue then
      FLimitHiSysEa := FLimitHiSysEa or AIndex
    else
      FLimitHiSysEa := FLimitHiSysEa and not AIndex;
  end;
5
ответ дан 28 November 2019 в 20:52
поделиться

Ну, в основном необходимо перейти к грязному с побитовой обработкой.

Да ведь а именно, необходимо ли сохранить ту структуру?

, Если только необходимо говорить с программой прежней версии, которая или говорит на этом диалекте (TCP/IP или подобный) или хранит данные этим способом (файлы, и т.д.), тогда я отобразил бы нормальную структуру Дельфи на совместимую разрядную версию. Другими словами, я использовал бы обычно структурированную структуру Дельфи в памяти и код записи, чтобы записать и считать ту структуру совместимым способом.

, Если бы необходимо сохранить память, я сделал бы методов get и методы set, которые управляют битами внутренних целых чисел или подобный. Это окажет влияние производительности, но не намного больше, чем, что имела бы исходная C программа, единственная разница - то, что побитовая обработка была бы добавлена волшебством компилятора в версии C, тогда как необходимо будет записать его сами.

, Если бы у Вас нет многих записей в памяти, и не должными быть говорить с другой программой, я использовал бы естественную структуру Дельфи. Компромисс для более высокой производительности будет большей используемой памятью.

, Но все это зависит от Ваших критериев.

В любом случае, Вы не будете в состоянии уговорить компилятор Дельфи на выполнение того же задания для Вас как компилятор C.

УПАКОВАННАЯ ЗАПИСЬ, предложенная другим здесь, не делает этого и никогда не предназначалась для. Это только удалит дополнение выравнивания для помещения целых чисел на 32-разрядные границы и подобный, но не упакует несколько полей в один байт.

Примечание, что распространенный способ сделать это через SETS Дельфи, которые реализуют внутренне битовые поля использования. Снова, у Вас будет различный код, чем вариант C.

0
ответ дан 28 November 2019 в 20:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: