I'm using json to output a bunch of classes.
The problem that i am trying to solve is what is the best way to output json for a nested class. The following simple example highlights the problem.
# python 3.x
import json
class Class1:
def __init__(self):
self.a = 'this'
self.b = 33
def toJSON(self):
return json.dumps({'a': self.a,
'b': self.b},
sort_keys=False, indent=2, separators=(',', ': '))
class Class2:
def __init__(self):
self.x = 'hello'
self.y = Class1()
self.z = 'world'
def toJSON(self):
return json.dumps({'x': self.x,
'y': self.y.toJSON(),
'z': self.z},
sort_keys=False, indent=2, separators=(',', ': '))
if __name__ == '__main__':
a = Class2()
print(a.toJSON())
This is the output I'm getting. Which contains control characters
{
"x": "hello",
"y": "{\n \"a\": \"this\",\n \"b\": 33\n}",
"z": "world"
}
This is the output I want would look something like this
{
"x":"hello",
"y":{
"a":"this",
"b":33
},
"z":"world"
}
Any assistance would be greatly appreciated.
I think you could implement cls encoder and then pass cls to json.dumps function like the following example.
import json
class Class1:
def __init__(self):
self.a = 'this'
self.b = 33
class Class2:
def __init__(self):
self.x = 'hello'
self.y = Class1()
self.z = 'world'
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if hasattr(obj, '__dict__'):
return obj.__dict__
else:
return json.JSONEncoder.default(self, obj)
if __name__ == '__main__':
a = Class2()
print(json.dumps(a, cls=ComplexEncoder, sort_keys=False, indent=2, separators=(',', ': ')))
You are dumping a JSON as string. Loading it as JSON and then returning would help
# python 3.x
import json
class Class1:
def __init__(self):
self.a = 'this'
self.b = 33
def toJSON(self):
return json.loads(json.dumps({'a': self.a,
'b': self.b},
sort_keys=False, indent=4, separators=(',', ': ')))
class Class2:
def __init__(self):
self.x = 'hello'
self.y = Class1()
self.z = 'world'
def toJSON(self):
return json.loads(json.dumps({'x': self.x,
'y': self.y.toJSON(),
'z': self.z},
sort_keys=False, indent=2, separators=(',', ': ')))
if __name__ == '__main__':
a = Class2()
print(a.toJSON())
Output :
{'x': 'hello', 'y': {'a': 'this', 'b': 33}, 'z': 'world'}
Related
I try to made multilabel classification using lstm arch and pytroch lib. But unfortunately it does't train.
BATCH_SIZE=1
INPUT_LENGTH=5
#data generation
df=pd.DataFrame({"product_group":[INPUT_LENGTH//2*[random.randint(1,20)]+INPUT_LENGTH//2*
[random.randint(1,20)] for _ in range(3)],"test_data":[[1,2],[3],[2]]})
target_vector=np.array([1,2,3])
output_dim=3
# make it more
df=pd.concat([df,df,df,df,df])
train, test = train_test_split(df, test_size=0.2, random_state=0)
class CustomDataset(Dataset):
def __init__(self, ddf):
self.ddf=ddf
def __len__(self):
return self.ddf.shape[0]
def __getitem__(self, idx):
data=self.ddf.iloc[idx]
# get index of target value
list_target_elements=[]
for val in data.test_data:
list_target_elements.append(target_vector.tolist().index(val))
#creating empty tensor
target=torch.zeros(len(target_vector))
for index in list_target_elements:
target[index]=1
return torch.tensor(data.product_group),target
dataset_train=CustomDataset(train)
dataset_test=CustomDataset(test)
train_dataloader = DataLoader(dataset_train, batch_size=BATCH_SIZE, shuffle=True,drop_last=False)
test_dataloader = DataLoader(dataset_test, batch_size=BATCH_SIZE, shuffle=True,drop_last=False)
class LSTMModel(nn.Module):
def __init__(self, input_dim, hidden_dim, layer_dim, output_dim, dropout_prob):
super(LSTMModel, self).__init__()
self.embeding= nn.Embedding(21, 50)
self.hidden_dim = hidden_dim
self.layer_dim = layer_dim
self.lstm = nn.LSTM(
input_dim, hidden_dim, layer_dim, batch_first=True, dropout=dropout_prob
)
self.fc1 = nn.Linear(hidden_dim, output_dim)
self.sigmoid=torch.nn.Sigmoid()
def forward(self, x):
h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim)
c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim)
x=self.embeding(x)
out, (hn, cn) = self.lstm(x, (h0, c0))
out = out[:, -1, :]
out = self.fc1(out)
out=self.sigmoid(out)
return out
model =LSTMModel(input_dim=50,hidden_dim=10,layer_dim=20,output_dim=output_dim,dropout_prob=0.2)
x,y=(next(iter(train_dataloader)))
after i got:
x:tensor([[17, 17, 20, 20]])
y:tensor([[0., 0., 1.]])
model(x) shows tensor([[0.4539, 0.4767, 0.4881]], grad_fn=SigmoidBackward0)
def train_model(model, loss, optimizer,scheduler, num_epochs):
precision_stats = {
'train': [],
"val": []
}
recall_stats = {
'train': [],
"val": []
}
loss_stats = {
'train': [],
"val": []
}
for e in tqdm(range(1, num_epochs+1)):
# TRAINING
train_epoch_loss = 0
train_epoch_recall = 0
train_epoch_precision = 0
model.train()
for x, y in tqdm(train_dataloader):
x = x.to(device)
y = y.to(device)
optimizer.zero_grad()
y_train_pred = model(x)
train_loss = loss(y_train_pred, y)
train_loss.backward()
optimizer.step()
scheduler.step()
pred = np.array(y_train_pred > 0.5, dtype=float)
train_recall = recall_score(y_true=y, y_pred=pred,average='micro',zero_division=0)
train_precision = precision_score(y_true=y, y_pred=pred,average='micro',zero_division=0)
train_epoch_loss += train_loss.item()
train_epoch_recall += train_recall.item()
train_epoch_precision += train_precision.item()
loss_stats['train'].append(train_epoch_loss/len(train_dataloader))
recall_stats['train'].append(train_epoch_recall/len(train_dataloader))
precision_stats['train'].append(train_epoch_precision/len(train_dataloader))
print(f'Epoch {e+0:03}: | Loss: {train_epoch_loss/len(train_dataloader):.5f} | recall: {train_epoch_recall/len(train_dataloader):.3f} | precision:{train_epoch_precision/len(train_dataloader):.3f}')
And finally launch train cycle:
lr=0.01
epoch=200
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = model.to(device)
loss = torch.nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
train_model(model,loss,optimizer,scheduler,epoch)
this code work without errors, but model doesn't train
I am trying to convert COCO json file to LabelMe json file. I used a python script called "coco2labelme.py" to convert the json file.
It successfully converts the json file, the only problem is that I get an error every time I try to load the converted json file in LabelMe. An error occurs regarding the 'imageData' of the file.
Does anyone have an idea on how to convert from COCO to LabelMe format with the image data?
below is the code for coco2labelme.py
[Source: https://gist.github.com/travishsu/6efa5c9fb92ece37b4748036026342f6]
import os
import json
import subprocess
import numpy as np
import pandas as pd
from skimage.measure import find_contours
class CocoDatasetHandler:
def __init__(self, jsonpath, imgpath):
with open(jsonpath, 'r') as jsonfile:
ann = json.load(jsonfile)
images = pd.DataFrame.from_dict(ann['images']).set_index('id')
annotations = pd.DataFrame.from_dict(ann['annotations']).set_index('id')
categories = pd.DataFrame.from_dict(ann['categories']).set_index('id')
annotations = annotations.merge(images, left_on='image_id', right_index=True)
annotations = annotations.merge(categories, left_on='category_id', right_index=True)
annotations = annotations.assign(
shapes=annotations.apply(self.coco2shape, axis=1))
self.annotations = annotations
self.labelme = {}
self.imgpath = imgpath
self.images = pd.DataFrame.from_dict(ann['images']).set_index('file_name')
def coco2shape(self, row):
if row.iscrowd == 1:
shapes = self.rle2shape(row)
elif row.iscrowd == 0:
shapes = self.polygon2shape(row)
return shapes
def rle2shape(self, row):
rle, shape = row['segmentation']['counts'], row['segmentation']['size']
mask = self._rle_decode(rle, shape)
padded_mask = np.zeros(
(mask.shape[0]+2, mask.shape[1]+2),
dtype=np.uint8,
)
padded_mask[1:-1, 1:-1] = mask
points = find_contours(mask, 0.5)
shapes = [
[[int(point[1]), int(point[0])] for point in polygon]
for polygon in points
]
return shapes
def _rle_decode(self, rle, shape):
mask = np.zeros([shape[0] * shape[1]], np.bool)
for idx, r in enumerate(rle):
if idx < 1:
s = 0
else:
s = sum(rle[:idx])
e = s + r
if e == s:
continue
assert 0 <= s < mask.shape[0]
assert 1 <= e <= mask.shape[0], "shape: {} s {} e {} r {}".format(shape, s, e, r)
if idx % 2 == 1:
mask[s:e] = 1
# Reshape and transpose
mask = mask.reshape([shape[1], shape[0]]).T
return mask
def polygon2shape(self, row):
# shapes: (n_polygons, n_points, 2)
shapes = [
[[int(points[2*i]), int(points[2*i+1])] for i in range(len(points)//2)]
for points in row.segmentation
]
return shapes
def coco2labelme(self):
fillColor = [255, 0, 0, 128]
lineColor = [0, 255, 0, 128]
groups = self.annotations.groupby('file_name')
for file_idx, (filename, df) in enumerate(groups):
record = {
'imageData': None,
'fillColor': fillColor,
'lineColor': lineColor,
'imagePath': filename,
'imageHeight': int(self.images.loc[filename].height),
'imageWidth': int(self.images.loc[filename].width),
}
record['shapes'] = []
instance = {
'line_color': None,
'fill_color': None,
'shape_type': "polygon",
}
for inst_idx, (_, row) in enumerate(df.iterrows()):
for polygon in row.shapes:
copy_instance = instance.copy()
copy_instance.update({
'label': row['name'],
'group_id': inst_idx,
'points': polygon
})
record['shapes'].append(copy_instance)
if filename not in self.labelme.keys():
self.labelme[filename] = record
def save_labelme(self, file_names, dirpath, save_json_only=False):
if not os.path.exists(dirpath):
os.makedirs(dirpath)
else:
raise ValueError(f"{dirpath} has existed")
for file in file_names:
filename = os.path.basename(os.path.splitext(file)[0])
with open(os.path.join(dirpath, filename+'.json'), 'w') as jsonfile:
json.dump(self.labelme[file], jsonfile, ensure_ascii=True, indent=2)
if not save_json_only:
subprocess.call(['cp', os.path.join(self.imgpath, file), dirpath])
ds = CocoDatasetHandler('cocodataset/annotations/instances_train2014.json', 'cocodataset/train2014/')
ds.coco2labelme()
ds.save_labelme(ds.labelme.keys(), 'cocodataset/labelme/train2014')
QTableView has been instantiated, use QSqlTableModel in PYQT5 to read MySQL database, and use setmodel() to display correctly in QTableView. Freeze the first row and first column using FreezeTableView but no data is displayed in the instantiated tableView. It needs show() to display the data in a new window. How can I display the data in the instantiated tableView instead of in a new window? Thanks!
Ui_untitled.py
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(978, 828)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeView_1 = QtWidgets.QTreeView(self.centralwidget)
self.treeView_1.setEnabled(False)
self.treeView_1.setGeometry(QtCore.QRect(10, 11, 191, 771))
self.treeView_1.setObjectName("treeView_1") #Omitted below
mainwindown.py
from ui_untitled import Ui_MainWindow
class MainForm(QMainWindow, Ui_MainWindow):
def __init__(self, pareng=None):
super(MainForm, self).__init__(pareng)
self.setupUi(self)
def on_treeView_clicked(self, index):
name = index.data()
self.tableModel_1 = QSqlTableModel()
self.tableModel_1.setTable("name")
self.tableModel_1.setEditStrategy(QSqlTableModel.OnRowChange)
self.tableModel_1.setFilter(self.tr("name_no = %s"%name))
self.tableModel_1.select()
self.tableView_1 = QTableView()
#self.tableView_1.setModel(self.tableModel_1)
self.tableView_1 = FreezeTableView(self.tableModel_1)
#self.tableView_1.show() #No data displayed after cancel
class FreezeTableView(QTableView, QAbstractSlider):
def __init__(self, model):
super(FreezeTableView, self).__init__()
self.model = model
self.frozenTableView = QTableView(self)
self.horizontalView = QTableView(self)
self.up = True
self.init()
def init(self):
self.setModel(self.model)
#print(self.model.rowCount(), self.model.ColumnCount())
self.frozenTableInit()
self.horizontalViewInit()
self.horizontalHeader().sectionResized.connect(self.updateSectionWidth)
self.verticalHeader().sectionResized.connect(self.updateSectionHeight)
self.verticalScrollBar().valueChanged.connect(self.vConnectFV)
self.frozenTableView.verticalScrollBar().valueChanged.connect(self.fVConnectV)
self.horizontalScrollBar().valueChanged.connect(self.hConnectH)
def vConnectFV(self, a0: int):
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.stackUnder(self.horizontalView)
self.frozenTableView.verticalScrollBar().setValue(a0)
def fVConnectV(self, a0: int):
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.stackUnder(self.horizontalView)
self.verticalScrollBar().setValue(a0)
def hConnectH(self, a0: int):
self.viewport().stackUnder(self.horizontalView)
self.horizontalView.stackUnder(self.frozenTableView)
self.horizontalView.horizontalScrollBar().setValue(a0)
def frozenTableInit(self):
self.frozenTableView.setModel(self.model)
self.frozenTableView.verticalHeader().hide()
self.frozenTableView.setFocusPolicy(Qt.NoFocus)
self.frozenTableView.horizontalHeader().setFixedHeight(self.horizontalHeader().height())
self.frozenTableView.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.setStyleSheet('QTableView {'
'border: none;'
'background-color: #8EDE21;'
'selection-background-color: #999}')
self.frozenTableView.setSelectionModel(self.selectionModel())
[self.frozenTableView.setColumnHidden(col, True) for col in range(1, self.model.columnCount())]
self.frozenTableView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.frozenTableView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.frozenTableView.show()
self.updateFrozenTableGeometry()
self.frozenTableView.setVerticalScrollMode(self.ScrollPerPixel)
self.setVerticalScrollMode(self.ScrollPerPixel)
self.setHorizontalScrollMode(self.ScrollPerPixel)
def horizontalViewInit(self):
self.horizontalView.setModel(self.model)
self.horizontalView.horizontalHeader().hide()
self.horizontalView.setFocusPolicy(Qt.NoFocus)
self.horizontalView.verticalHeader().setFixedWidth(self.verticalHeader().width())
self.horizontalView.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
self.frozenTableView.stackUnder(self.horizontalView)
self.horizontalView.setStyleSheet('QTableView { border: none;'
'background-color: #8EDE21;'
'selection-background-color: #999}')
self.horizontalView.setSelectionModel(self.selectionModel())
[self.horizontalView.setRowHidden(row, True) for row in range(1, self.model.rowCount())]
self.horizontalView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.horizontalView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.horizontalView.show()
self.updateFrozenTableGeometry()
self.horizontalView.setHorizontalScrollMode(self.ScrollPerPixel)
def updateFrozenTableGeometry(self):
self.frozenTableView.setGeometry(self.verticalHeader().width() + self.frameWidth(),
self.frameWidth(), self.columnWidth(0),
self.viewport().height() + self.horizontalHeader().height())
self.horizontalView.setGeometry(self.frameWidth(), self.frameWidth() + self.horizontalHeader().height(),
self.viewport().width() + self.verticalHeader().width(), self.rowHeight(0))
def updateSectionWidth(self, logicalIndex, oldSize, newSize):
self.horizontalView.setColumnWidth(logicalIndex, newSize)
if not logicalIndex:
self.frozenTableView.setColumnWidth(0, newSize)
self.updateFrozenTableGeometry()
def updateSectionHeight(self, logicalIndex, oldSize, newSize):
self.frozenTableView.setRowHeight(logicalIndex, newSize)
if not logicalIndex:
self.horizontalView.setRowHeight(0, newSize)
self.updateFrozenTableGeometry()
def resizeEvent(self, e: QtGui.QResizeEvent) -> None:
QTableView.resizeEvent(self, e)
self.updateFrozenTableGeometry()
def scrollTo(self, index: QtCore.QModelIndex, hint: QAbstractItemView.ScrollHint = ...) -> None:
print(index.row, index.column, self.model.data(index))
if index.column() > 0 or index.row() > 0:
QTableView.scrollTo(self, index, hint)
def moveCursor(self, cursorAction: QAbstractItemView.CursorAction,
modifiers: typing.Union[QtCore.Qt.KeyboardModifiers,
QtCore.Qt.KeyboardModifier]) -> QtCore.QModelIndex:
current = QTableView.moveCursor(self, cursorAction, modifiers)
if cursorAction == QAbstractItemView.MoveLeft and current.column() > 0 \
and self.visualRect(current).topLeft().x() < self.frozenTableView.columnWidth(0):
newValue = self.verticalScrollBar().value() + self.visualRect(current).topLeft().x() \
- self.frozenTableView.columnWidth(0)
self.horizontalScrollBar().setValue(newValue)
if cursorAction == QAbstractItemView.MoveUp and current.row() > 0 \
and self.visualRect(current).topLeft().y() < self.horizontalView.rowHeight(0):
newValue = self.horizontalScrollBar().value() + self.visualRect(current).topLeft().y() \
- self.horizontalView.rowHeight(0)
self.verticalScrollBar().setValue(newValue)
return current
'from ui_untitled import Ui_MainWindow
class MainForm(QMainWindow, Ui_MainWindow):
def __init__(self, pareng=None):
super(MainForm, self).__init__(pareng)
self.setupUi(self)
def on_treeView_clicked(self, index): #treeView双击显示Qmodelidx
name = index.data()
self.tableModel_1 = QSqlTableModel()
self.tableModel_1.setTable("name")
self.tableModel_1.setEditStrategy(QSqlTableModel.OnRowChange)
self.tableModel_1.setFilter(self.tr("name_no = %s"%name))
self.tableModel_1.select()
self.tableView_1 = QTableView()
#self.tableView_1.setModel(self.tableModel_1)
self.tableView_1 = FreezeTableView(self.tableModel_1)
#self.tableView_1.show() #No data displayed after cancel
class FreezeTableView(QTableView, QAbstractSlider):
def __init__(self, model):
super(FreezeTableView, self).__init__()
self.model = model
self.frozenTableView = QTableView(self)
self.horizontalView = QTableView(self)
self.up = True
self.init()
def init(self):
self.setModel(self.model)
#print(self.model.rowCount(), self.model.ColumnCount())
self.frozenTableInit()
self.horizontalViewInit()
self.horizontalHeader().sectionResized.connect(self.updateSectionWidth)
self.verticalHeader().sectionResized.connect(self.updateSectionHeight)
self.verticalScrollBar().valueChanged.connect(self.vConnectFV)
self.frozenTableView.verticalScrollBar().valueChanged.connect(self.fVConnectV)
self.horizontalScrollBar().valueChanged.connect(self.hConnectH)
def vConnectFV(self, a0: int):
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.stackUnder(self.horizontalView)
self.frozenTableView.verticalScrollBar().setValue(a0)
def fVConnectV(self, a0: int):
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.stackUnder(self.horizontalView)
self.verticalScrollBar().setValue(a0)
def hConnectH(self, a0: int):
self.viewport().stackUnder(self.horizontalView)
self.horizontalView.stackUnder(self.frozenTableView)
self.horizontalView.horizontalScrollBar().setValue(a0)
def frozenTableInit(self):
self.frozenTableView.setModel(self.model)
self.frozenTableView.verticalHeader().hide()
self.frozenTableView.setFocusPolicy(Qt.NoFocus)
self.frozenTableView.horizontalHeader().setFixedHeight(self.horizontalHeader().height())
self.frozenTableView.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
self.viewport().stackUnder(self.frozenTableView)
self.frozenTableView.setStyleSheet('QTableView {'
'border: none;'
'background-color: #8EDE21;'
'selection-background-color: #999}')
self.frozenTableView.setSelectionModel(self.selectionModel())
[self.frozenTableView.setColumnHidden(col, True) for col in range(1, self.model.columnCount())]
self.frozenTableView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.frozenTableView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.frozenTableView.show()
self.updateFrozenTableGeometry()
self.frozenTableView.setVerticalScrollMode(self.ScrollPerPixel)
self.setVerticalScrollMode(self.ScrollPerPixel)
self.setHorizontalScrollMode(self.ScrollPerPixel)
def horizontalViewInit(self):
self.horizontalView.setModel(self.model)
self.horizontalView.horizontalHeader().hide()
self.horizontalView.setFocusPolicy(Qt.NoFocus)
self.horizontalView.verticalHeader().setFixedWidth(self.verticalHeader().width())
self.horizontalView.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
self.frozenTableView.stackUnder(self.horizontalView)
self.horizontalView.setStyleSheet('QTableView { border: none;'
'background-color: #8EDE21;'
'selection-background-color: #999}')
self.horizontalView.setSelectionModel(self.selectionModel())
[self.horizontalView.setRowHidden(row, True) for row in range(1, self.model.rowCount())]
self.horizontalView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.horizontalView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.horizontalView.show()
self.updateFrozenTableGeometry()
self.horizontalView.setHorizontalScrollMode(self.ScrollPerPixel)
def updateFrozenTableGeometry(self):
self.frozenTableView.setGeometry(self.verticalHeader().width() + self.frameWidth(),
self.frameWidth(), self.columnWidth(0),
self.viewport().height() + self.horizontalHeader().height())
self.horizontalView.setGeometry(self.frameWidth(), self.frameWidth() + self.horizontalHeader().height(),
self.viewport().width() + self.verticalHeader().width(), self.rowHeight(0))
def updateSectionWidth(self, logicalIndex, oldSize, newSize):
self.horizontalView.setColumnWidth(logicalIndex, newSize)
if not logicalIndex:
self.frozenTableView.setColumnWidth(0, newSize)
self.updateFrozenTableGeometry()
def updateSectionHeight(self, logicalIndex, oldSize, newSize):
self.frozenTableView.setRowHeight(logicalIndex, newSize)
if not logicalIndex:
self.horizontalView.setRowHeight(0, newSize)
self.updateFrozenTableGeometry()
def resizeEvent(self, e: QtGui.QResizeEvent) -> None:
QTableView.resizeEvent(self, e)
self.updateFrozenTableGeometry()
def scrollTo(self, index: QtCore.QModelIndex, hint: QAbstractItemView.ScrollHint = ...) -> None:
print(index.row, index.column, self.model.data(index))
if index.column() > 0 or index.row() > 0:
QTableView.scrollTo(self, index, hint)
def moveCursor(self, cursorAction: QAbstractItemView.CursorAction,
modifiers: typing.Union[QtCore.Qt.KeyboardModifiers,
QtCore.Qt.KeyboardModifier]) -> QtCore.QModelIndex:
current = QTableView.moveCursor(self, cursorAction, modifiers)
if cursorAction == QAbstractItemView.MoveLeft and current.column() > 0 \
and self.visualRect(current).topLeft().x() < self.frozenTableView.columnWidth(0):
newValue = self.verticalScrollBar().value() + self.visualRect(current).topLeft().x() \
- self.frozenTableView.columnWidth(0)
self.horizontalScrollBar().setValue(newValue)
if cursorAction == QAbstractItemView.MoveUp and current.row() > 0 \
and self.visualRect(current).topLeft().y() < self.horizontalView.rowHeight(0):
newValue = self.horizontalScrollBar().value() + self.visualRect(current).topLeft().y() \
- self.horizontalView.rowHeight(0)
self.verticalScrollBar().setValue(newValue)
return current
the codes I have on scrapy are shown below:
def parse(self, response):
for quote in response.css('div.search-item '):
f = quote.css('a.stack::attr(href)').extract_first()
f = response.urljoin(f)
# print(f)
yield {
'text': quote.css('span.tags::text').extract_first(),
'title': quote.css('h3 em::text').extract_first(),
}
yield response.follow(f, self.parse_program)
def parse_program(self, response):
def extract_with_css(query):
return response.css(query).extract_first().strip()
yield {
'name': extract_with_css('div.headline h1::text'),}
The result turn out to be like:
{'text':"sdada",'title':"12321q"}
{'name':"sdasdsa"}
I want to make it like:
{'text':"sdada",'title':"12321q",'name':"sdasdsa"}
what should I do?
You need to use request meta for this, and yield the item only when you have all the data
def parse(self, response):
for quote in response.css('div.search-item '):
f = quote.css('a.stack::attr(href)').extract_first()
f = response.urljoin(f)
# print(f)
data = {
'text': quote.css('span.tags::text').extract_first(),
'title': quote.css('h3 em::text').extract_first(),
}
yield response.follow(f, self.parse_program, meta={"data": data})
def parse_program(self, response):
def extract_with_css(query):
return response.css(query).extract_first().strip()
data = response.meta["data"]
data['name'] = extract_with_css('div.headline h1::text')
yield data
I made a new example which shows much better what I am trying to do. The new example gives the following ouput. Is there a way that the data can go into the respective store key (the {} brackets)?
{
"copy": [
[
[
5.0,
8.0,
9.0
]
],
[
[
4.0,
0.0,
1.0
]
]
],
"name": "dataset1",
"sets": [
{
"store": {},
"type": "vector"
},
{
"store": {},
"type": "vector"
}
]
}
New example
from gi.repository import Gtk
import json
import random
class Vector(object):
def __init__(self, data):
self.store = Gtk.ListStore(float, float, float)
self.store.append([data[0], data[1], data[2]])
self.type = "vector"
def return_data(self):
store_data = []
def iterate_over_data(model, path, itr):
row = model[path]
store_data.append([row[0], row[1], row[2]])
self.store.foreach(iterate_over_data)
return store_data
class DataSet(object):
def __init__(self, name):
self.name = name
self.sets = []
def add_vector(self):
data = [random.randint(0,9) for x in range(3)]
self.sets.append(Vector(data))
def to_json(self):
self.copy = []
for s in self.sets:
self.copy.append(s.return_data())
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
obj1 = DataSet("dataset1")
for x in range(2):
obj1.add_vector()
print(obj1.to_json())
Old example
I am currently figuring out how to serialize a Gtk ListStore that is nested in a Gtk TreeStore. I got a small example to work, but am not sure if this approach will scale for programs that have more data attached (For example the layer object could hold a color or a date of creation). Is there maybe another way to to this?
My current approach is to gather the data in list and dictionary form myself and then just create the JSON-dump. I have the feeling that this would be rather difficult to maintain if I need to attach 25 values to each layer-object.
from gi.repository import Gtk, Gdk
import json
import random
class LayerTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Name", renderer, text=0)
self.append_column(column)
class DataTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
self.store = store
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Data", renderer, text=0)
self.append_column(column)
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="TreeView Serialize")
self.connect("delete-event", Gtk.main_quit)
self.set_border_width(10)
self.set_default_size(400, 300)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True)
self.add(vbox)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
button = Gtk.Button("Cut")
button.connect("clicked", self.on_cut_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_COPY)
button.connect("clicked", self.on_copy_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_PASTE)
button.connect("clicked", self.on_paste_clicked)
hbox.pack_start(button, True, True, 0)
vbox.add(hbox)
self.layer_store = Gtk.TreeStore(str, object, object)
self.layer_view = LayerTreeView(self.layer_store)
self.layer_sw = Gtk.ScrolledWindow()
self.data_sw = Gtk.ScrolledWindow()
self.layer_sw.add(self.layer_view)
treebox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6, expand=True)
treebox.pack_start(self.layer_sw, True, True, 0)
treebox.pack_start(self.data_sw, True, True, 0)
vbox.add(treebox)
self.select = self.layer_view.get_selection()
self.select.connect("changed", self.on_selection_changed)
self.add_test_data()
def add_test_data(self):
for x in range(3):
data_store = Gtk.ListStore(str)
data_view = DataTreeView(data_store)
for y in range(5):
data_store.append([str(y+x)])
self.layer_store.append(None, ["Data {}".format(x), data_store, data_view])
def on_selection_changed(self, selection):
"""
When layer is switched load respective data
"""
model, treeiter = selection.get_selected()
if treeiter != None:
data_view = model[treeiter][2]
child = self.data_sw.get_child()
if child != None:
self.data_sw.remove(self.data_sw.get_child())
self.data_sw.add(data_view)
self.show_all()
def on_cut_clicked(self, button):
pass
def on_copy_clicked(self, button):
copy_list = ["safe-to-paste"]
data_dict = {}
for row in self.layer_store:
name = row[0]
data_obj = row[1]
value_list = []
for datarow in data_obj:
value = datarow[0]
value_list.append(value)
data_dict[name] = value_list
copy_list.append(data_dict)
data = json.dumps(copy_list)
self.clipboard.set_text(data, -1)
def on_paste_clicked(self, button):
paste_str = self.clipboard.wait_for_text()
try:
parse = json.loads(paste_str)
json_str = True
except:
json_str = False
if json_str is False:
return
keyword = parse[0]
if keyword != "safe-to-paste":
return
data_dict = parse[1]
for x in data_dict:
data_list = data_dict[x]
data_store = Gtk.ListStore(str)
data_view = DataTreeView(data_store)
for y in data_list:
data_store.append([str(y)])
self.layer_store.append(None, [x, data_store, data_view])
win = MainWindow()
win.show_all()
Gtk.main()
I have an improved version of your code with dict comprehension and #staticmethod that makes the signal callbacks more readable and shorter. Nevertheless, this does not really solve your problem as it still generates the json manually. If the ListStore gets more complex, it would probably be better to let the DataListStore class generate its own json with a corresponding method.
from gi.repository import Gtk, Gdk
import json
class LayerTreeView(Gtk.TreeView):
def __init__(self, store):
Gtk.TreeView.__init__(self, store)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Name", renderer, text=0)
self.append_column(column)
class DataTreeView(Gtk.TreeView):
def __init__(self):
Gtk.TreeView.__init__(self)
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Data", renderer, text=0)
self.append_column(column)
class DataListStore(Gtk.ListStore):
#staticmethod
def from_json(*args, values=[]):
store = DataListStore(*args)
for value in values:
store.append((value,))
return store
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="TreeView Serialize")
self.connect("delete-event", Gtk.main_quit)
self.set_border_width(10)
self.set_default_size(400, 300)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True)
self.add(vbox)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
button = Gtk.Button("Cut")
button.connect("clicked", self.on_cut_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_COPY)
button.connect("clicked", self.on_copy_clicked)
hbox.pack_start(button, True, True, 0)
button = Gtk.Button(stock=Gtk.STOCK_PASTE)
button.connect("clicked", self.on_paste_clicked)
hbox.pack_start(button, True, True, 0)
vbox.add(hbox)
self.layer_store = Gtk.TreeStore(str, object)
self.layer_view = LayerTreeView(self.layer_store)
self.data_view = DataTreeView()
layer_sw = Gtk.ScrolledWindow()
layer_sw.add(self.layer_view)
data_sw = Gtk.ScrolledWindow()
data_sw.add(self.data_view)
treebox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6, expand=True)
treebox.pack_start(layer_sw, True, True, 0)
treebox.pack_start(data_sw, True, True, 0)
vbox.add(treebox)
select = self.layer_view.get_selection()
select.connect("changed", self.on_selection_changed)
self.add_test_data()
def add_test_data(self):
for x in range(3):
data_list = [str(y+x) for y in range(5)]
self.layer_store.append(None, ["Data {}".format(x), data_list])
def on_selection_changed(self, selection):
"""
When layer is switched load respective data
"""
model, treeiter = selection.get_selected()
if treeiter != None:
self.data_view.set_model(
DataListStore.from_json(str, values=model[treeiter][1])
)
def on_cut_clicked(self, button):
pass
def on_copy_clicked(self, button):
copy_list = [
'safe-to-paste',
{row[0]: row[1] for row in self.layer_store},
]
data = json.dumps(copy_list)
self.clipboard.set_text(data, -1)
def on_paste_clicked(self, button):
paste_str = self.clipboard.wait_for_text()
try:
parse = json.loads(paste_str)
except:
return
if parse[0] != "safe-to-paste":
return
data_dict = parse[1]
for x in data_dict:
self.layer_store.append(None, [x, data_dict[x]])
win = MainWindow()
win.show_all()
Gtk.main()