CC中有两个地方使用了文件保存,一个是MainWindow,另一个是ccCommandLineParser。

MainWindow的保存按钮关联的槽是doActionSaveFile()方法,实现了点云和Mesh的保存。

  1 void MainWindow::doActionSaveFile()
  2 {
  3     size_t selNum = m_selectedEntities.size();
  4     if (selNum == 0)
  5         return;
  6
  7     ccHObject clouds("clouds");
  8     ccHObject meshes("meshes");
  9     ccHObject images("images");
 10     ccHObject polylines("polylines");
 11     ccHObject other("other");
 12     ccHObject otherSerializable("serializable");
 13     ccHObject::Container entitiesToDispatch;
 14     entitiesToDispatch.insert(entitiesToDispatch.begin(),m_selectedEntities.begin(),m_selectedEntities.end());
 15     ccHObject entitiesToSave;
 16     while (!entitiesToDispatch.empty())
 17     {
 18         ccHObject* child = entitiesToDispatch.back();
 19         entitiesToDispatch.pop_back();
 20
 21         if (child->isA(CC_TYPES::HIERARCHY_OBJECT))
 22         {
 23             for (unsigned j=0; j<child->getChildrenNumber(); ++j)
 24                 entitiesToDispatch.push_back(child->getChild(j));
 25         }
 26         else
 27         {
 28             //we put the entity in the container corresponding to its type
 29             ccHObject* dest = 0;
 30             if (child->isA(CC_TYPES::POINT_CLOUD))
 31                 dest = &clouds;
 32             else if (child->isKindOf(CC_TYPES::MESH))
 33                 dest = &meshes;
 34             else if (child->isKindOf(CC_TYPES::IMAGE))
 35                 dest = &images;
 36             else if (child->isKindOf(CC_TYPES::POLY_LINE))
 37                 dest = &polylines;
 38             else if (child->isSerializable())
 39                 dest = &otherSerializable;
 40             else
 41                 dest = &other;
 42
 43             assert(dest);
 44
 45             //we don't want double insertions if the user has clicked both the father and child
 46             if (!dest->find(child->getUniqueID()))
 47             {
 48                 dest->addChild(child,ccHObject::DP_NONE);
 49                 entitiesToSave.addChild(child,ccHObject::DP_NONE);
 50             }
 51         }
 52     }
 53
 54     bool hasCloud = (clouds.getChildrenNumber() != 0);
 55     bool hasMesh = (meshes.getChildrenNumber() != 0);
 56     bool hasImages = (images.getChildrenNumber() != 0);
 57     bool hasPolylines = (polylines.getChildrenNumber() != 0);
 58     bool hasSerializable = (otherSerializable.getChildrenNumber() != 0);
 59     bool hasOther = (other.getChildrenNumber() != 0);
 60
 61     int stdSaveTypes =        static_cast<int>(hasCloud)
 62                         +    static_cast<int>(hasMesh)
 63                         +    static_cast<int>(hasImages)
 64                         +    static_cast<int>(hasPolylines)
 65                         +    static_cast<int>(hasSerializable);
 66     if (stdSaveTypes == 0)
 67     {
 68         ccConsole::Error("Can't save selected entity(ies) this way!");
 69         return;
 70     }
 71
 72     //we set up the right file filters, depending on the selected
 73     //entities type (cloud, mesh, etc.).
 74     QStringList fileFilters;
 75     {
 76         const FileIOFilter::FilterContainer& filters = FileIOFilter::GetFilters();
 77         for (size_t i=0; i<filters.size(); ++i)
 78         {
 79             bool atLeastOneExclusive = false;
 80
 81             //current I/O filter
 82             const FileIOFilter::Shared filter = filters[i];
 83
 84             //does this filter can export one or several clouds?
 85             bool canExportClouds = true;
 86             if (hasCloud)
 87             {
 88                 bool isExclusive = true;
 89                 bool multiple = false;
 90                 canExportClouds = (        filter->canSave(CC_TYPES::POINT_CLOUD,multiple,isExclusive)
 91                                     &&    (multiple || clouds.getChildrenNumber() == 1) );
 92                 atLeastOneExclusive |= isExclusive;
 93             }
 94
 95             //does this filter can export one or several meshes?
 96             bool canExportMeshes = true;
 97             if (hasMesh)
 98             {
 99                 bool isExclusive = true;
100                 bool multiple = false;
101                 canExportMeshes = (        filter->canSave(CC_TYPES::MESH,multiple,isExclusive)
102                                     &&    (multiple || meshes.getChildrenNumber() == 1) );
103                 atLeastOneExclusive |= isExclusive;
104             }
105
106             //does this filter can export one or several polylines?
107             bool canExportPolylines = true;
108             if (hasPolylines)
109             {
110                 bool isExclusive = true;
111                 bool multiple = false;
112                 canExportPolylines = (    filter->canSave(CC_TYPES::POLY_LINE,multiple,isExclusive)
113                                     &&    (multiple || polylines.getChildrenNumber() == 1) );
114                 atLeastOneExclusive |= isExclusive;
115             }
116
117             //does this filter can export one or several images?
118             bool canExportImages = true;
119             if (hasImages)
120             {
121                 bool isExclusive = true;
122                 bool multiple = false;
123                 canExportImages = (        filter->canSave(CC_TYPES::IMAGE,multiple,isExclusive)
124                                     &&    (multiple || images.getChildrenNumber() == 1) );
125                 atLeastOneExclusive |= isExclusive;
126             }
127
128             //does this filter can export one or several other serializable entities?
129             bool canExportSerializables = true;
130             if (hasSerializable)
131             {
132                 //check if all entities have the same type
133                 {
134                     CC_CLASS_ENUM firstClassID = otherSerializable.getChild(0)->getUniqueID();
135                     for (unsigned j=1; j<otherSerializable.getChildrenNumber(); ++j)
136                     {
137                         if (otherSerializable.getChild(j)->getUniqueID() != firstClassID)
138                         {
139                             //we add a virtual second 'stdSaveType' so as to properly handle exlusivity
140                             ++stdSaveTypes;
141                             break;
142                         }
143                     }
144                 }
145
146                 for (unsigned j=0; j<otherSerializable.getChildrenNumber(); ++j)
147                 {
148                     ccHObject* child = otherSerializable.getChild(j);
149                     bool isExclusive = true;
150                     bool multiple = false;
151                     canExportSerializables &= (        filter->canSave(child->getUniqueID(),multiple,isExclusive)
152                                                 &&    (multiple || otherSerializable.getChildrenNumber() == 1) );
153                     atLeastOneExclusive |= isExclusive;
154                 }
155             }
156
157             bool useThisFilter =    canExportClouds
158                                 &&    canExportMeshes
159                                 &&    canExportImages
160                                 &&    canExportPolylines
161                                 &&    canExportSerializables
162                                 &&    (!atLeastOneExclusive || stdSaveTypes == 1);
163
164             if (useThisFilter)
165             {
166                 QStringList ff = filter->getFileFilters(false);
167                 for (int j=0; j<ff.size(); ++j)
168                     fileFilters.append(ff[j]);
169             }
170         }
171     }
172
173     //persistent settings
174     QSettings settings;
175     settings.beginGroup(ccPS::SaveFile());
176
177     //default filter
178     QString selectedFilter = fileFilters.first();
179     if (hasCloud)
180         selectedFilter = settings.value(ccPS::SelectedOutputFilterCloud(),selectedFilter).toString();
181     else if (hasMesh)
182         selectedFilter = settings.value(ccPS::SelectedOutputFilterMesh(), selectedFilter).toString();
183     else if (hasImages)
184         selectedFilter = settings.value(ccPS::SelectedOutputFilterImage(), selectedFilter).toString();
185     else if (hasPolylines)
186         selectedFilter = settings.value(ccPS::SelectedOutputFilterPoly(), selectedFilter).toString();
187
188     //default output path (+ filename)
189     QString currentPath = settings.value(ccPS::CurrentPath(),QApplication::applicationDirPath()).toString();
190     QString fullPathName = currentPath;
191     if (selNum == 1)
192     {
193         //hierarchy objects have generally as name: 'filename.ext (fullpath)'
194         //so we must only take the first part! (otherwise this type of name
195         //with a path inside perturbs the QFileDialog a lot ;))
196         QString defaultFileName(m_selectedEntities.front()->getName());
197         if (m_selectedEntities.front()->isA(CC_TYPES::HIERARCHY_OBJECT))
198         {
199             QStringList parts = defaultFileName.split(' ',QString::SkipEmptyParts);
200             if (parts.size() > 0)
201                 defaultFileName = parts[0];
202         }
203
204         //we remove the extension
205         defaultFileName = QFileInfo(defaultFileName).baseName();
206
207         if (!IsValidFileName(defaultFileName))
208         {
209             ccLog::Warning("[I/O] First entity's name would make an invalid filename! Can't use it...");
210             defaultFileName = "project";
211         }
212
213         fullPathName += QString("/") + defaultFileName;
214     }
215
216     //ask the user for the output filename
217     QString selectedFilename = QFileDialog::getSaveFileName(this,
218                                                             "Save file",
219                                                             fullPathName,
220                                                             fileFilters.join(s_fileFilterSeparator),
221                                                             &selectedFilter);
222
223     if (selectedFilename.isEmpty())
224     {
225         //process cancelled by the user
226         return;
227     }
228
229     //ignored items
230     if (hasOther)
231     {
232         ccConsole::Warning("[I/O] The following selected entites won't be saved:");
233         for (unsigned i=0; i<other.getChildrenNumber(); ++i)
234             ccConsole::Warning(QString("\t- %1s").arg(other.getChild(i)->getName()));
235     }
236
237     CC_FILE_ERROR result = CC_FERR_NO_ERROR;
238     FileIOFilter::SaveParameters parameters;
239     {
240         parameters.alwaysDisplaySaveDialog = true;
241         parameters.parentWidget = this;
242     }
243
244     //specific case: BIN format
245     if (selectedFilter == BinFilter::GetFileFilter())
246     {
247         if (selNum == 1)
248         {
249             result = FileIOFilter::SaveToFile(m_selectedEntities.front(),selectedFilename,parameters,selectedFilter);
250         }
251         else
252         {
253             //we'll regroup all selected entities in a temporary group
254             ccHObject tempContainer;
255             ConvertToGroup(m_selectedEntities,tempContainer,ccHObject::DP_NONE);
256             if (tempContainer.getChildrenNumber())
257             {
258                 result = FileIOFilter::SaveToFile(&tempContainer,selectedFilename,parameters,selectedFilter);
259             }
260             else
261             {
262                 ccLog::Warning("[I/O] None of the selected entities can be saved this way...");
263                 result = CC_FERR_NO_SAVE;
264             }
265         }
266     }
267     else if (entitiesToSave.getChildrenNumber() != 0)
268     {
269         //ignored items
270         /*if (hasSerializable)
271         {
272             if (!hasOther)
273                 ccConsole::Warning("[I/O] The following selected entites won't be saved:"); //display this warning only if not already done
274             for (unsigned i=0; i<otherSerializable.getChildrenNumber(); ++i)
275                 ccConsole::Warning(QString("\t- %1").arg(otherSerializable.getChild(i)->getName()));
276         }
277         //*/
278
279         result = FileIOFilter::SaveToFile(    entitiesToSave.getChildrenNumber() > 1 ? &entitiesToSave : entitiesToSave.getChild(0),
280                                             selectedFilename,
281                                             parameters,
282                                             selectedFilter);
283     }
284
285     //update default filters
286     if (hasCloud)
287         settings.setValue(ccPS::SelectedOutputFilterCloud(),selectedFilter);
288     if (hasMesh)
289         settings.setValue(ccPS::SelectedOutputFilterMesh(), selectedFilter);
290     if (hasImages)
291         settings.setValue(ccPS::SelectedOutputFilterImage(),selectedFilter);
292     if (hasPolylines)
293         settings.setValue(ccPS::SelectedOutputFilterPoly(), selectedFilter);
294
295     //we update current file path
296     currentPath = QFileInfo(selectedFilename).absolutePath();
297     settings.setValue(ccPS::CurrentPath(),currentPath);
298     settings.endGroup();
299 }

void MainWindow::doActionSaveFile()

再看看ccCommandLineParser的Parse方法:

 1 int ccCommandLineParser::Parse(int nargs, char** args)
 2 {
 3     if (!args || nargs < 2)
 4     {
 5         assert(false);
 6         return EXIT_SUCCESS;
 7     }
 8
 9     //reset default behavior(s)
10     s_loadParameters.autoComputeNormals = false;
11     s_MeshExportFormat = s_CloudExportFormat = BinFilter::GetFileFilter();
12     s_MeshExportExt = s_CloudExportExt = BinFilter::GetDefaultExtension();
13     s_precision = 12;
14     s_addTimestamp = true;
15     s_silentMode = false;
16     s_autoSaveMode = true;
17
18     //load arguments
19     QStringList arguments;
20     {
21         for (int i=1; i<nargs; ++i) //'i=1' because first argument is always program executable file!
22             arguments.push_back(QString(args[i]));
23     }
24     assert(!arguments.empty());
25
26     //specific command: silent mode (will prevent the console dialog from appearing!
27     if (IsCommand(arguments.front(),COMMAND_SILENT_MODE))
28     {
29         arguments.pop_front();
30         s_silentMode = true;
31     }
32
33     QDialog consoleDlg;
34     if (!s_silentMode)
35     {
36         //show console
37         Ui_commandLineDlg commandLineDlg;
38         commandLineDlg.setupUi(&consoleDlg);
39         consoleDlg.show();
40         ccConsole::Init(commandLineDlg.consoleWidget, &consoleDlg);
41         s_loadParameters.parentWidget = &consoleDlg;
42     }
43
44     //parse input
45     int result = ccCommandLineParser().parse(arguments,&consoleDlg);
46
47     if (!s_silentMode)
48     {
49         if (result == EXIT_SUCCESS)
50             QMessageBox::information(&consoleDlg,"Processed finished","Job done");
51         else
52             QMessageBox::warning(&consoleDlg,"Processed finished","An error occurred! Check console");
53     }
54
55     ccConsole::ReleaseInstance();
56
57     return result;
58 }

int ccCommandLineParser::Parse(int nargs, char** args)

该方法被main函数调用。

  1 //主程序入口,十分重要
  2 int main(int argc, char **argv)
  3 {
  4     //QT initialiation
  5     qccApplication app(argc, argv);
  6
  7     //Force 'english' local so as to get a consistent behavior everywhere
  8     QLocale::setDefault(QLocale::English);
  9
 10 #ifdef Q_OS_LINUX
 11     // we reset the numeric locale. As suggested in documetation
 12     // see http://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings
 13     // Basically - from doc: - "On Unix/Linux Qt is configured to use the system locale settings by default.
 14     // This can cause a conflict when using POSIX functions, for instance,
 15     // when converting between data types such as floats and strings"
 16     setlocale(LC_NUMERIC,"C");
 17 #endif
 18
 19 #ifdef USE_VLD
 20     VLDEnable();
 21 #endif
 22
 23     //splash screen
 24     QSplashScreen* splash = 0;
 25     QTime splashStartTime;
 26
 27     //Command line mode?
 28     bool commandLine = (argc > 1 && argv[1][0] == '-');
 29
 30     //specific case: translation file selection
 31     int lastArgumentIndex = 1;
 32     QTranslator translator;
 33     if (commandLine && QString(argv[1]).toUpper() == "-LANG")
 34     {
 35         QString langFilename = QString(argv[2]);
 36
 37         //Load translation file
 38         if (translator.load(langFilename, QCoreApplication::applicationDirPath()))
 39         {
 40             qApp->installTranslator(&translator);
 41         }
 42         else
 43         {
 44             QMessageBox::warning(0, QObject::tr("Translation"), QObject::tr("Failed to load language file '%1'").arg(langFilename));
 45         }
 46         commandLine = false;
 47         lastArgumentIndex = 3;
 48     }
 49
 50     //command line mode
 51     if (!commandLine)
 52     {
 53         //OpenGL?
 54         if (!QGLFormat::hasOpenGL())
 55         {
 56             QMessageBox::critical(0, "Error", "This application needs OpenGL to run!");
 57             return EXIT_FAILURE;
 58         }
 59
 60         //splash screen
 61         splashStartTime.start();
 62         QPixmap pixmap(QString::fromUtf8(":/CC/images/imLogoV2Qt.png"));
 63         splash = new QSplashScreen(pixmap,Qt::WindowStaysOnTopHint);
 64         splash->show();
 65         QApplication::processEvents();
 66     }
 67
 68     //global structures initialization
 69     ccTimer::Init();
 70     FileIOFilter::InitInternalFilters(); //load all known I/O filters (plugins will come later!)
 71     ccNormalVectors::GetUniqueInstance(); //force pre-computed normals array initialization
 72     ccColorScalesManager::GetUniqueInstance(); //force pre-computed color tables initialization
 73
 74     int result = 0;
 75
 76     if (commandLine)
 77     {
 78         //command line processing (no GUI)
 79         result = ccCommandLineParser::Parse(argc,argv);
 80     }
 81     else
 82     {
 83         //main window init.
 84         MainWindow* mainWindow = MainWindow::TheInstance();
 85         if (!mainWindow)
 86         {
 87             QMessageBox::critical(0, "Error", "Failed to initialize the main application window?!");
 88             return EXIT_FAILURE;
 89         }
 90         mainWindow->show();
 91         QApplication::processEvents();
 92
 93         if (argc > lastArgumentIndex)
 94         {
 95             if (splash)
 96                 splash->close();
 97
 98             //any additional argument is assumed to be a filename --> we try to load it/them
 99             QStringList filenames;
100             for (int i = lastArgumentIndex; i<argc; ++i)
101                 filenames << QString(argv[i]);
102
103             mainWindow->addToDB(filenames);
104         }
105
106         if (splash)
107         {
108             //we want the splash screen to be visible a minimum amount of time (1000 ms.)
109             while (splashStartTime.elapsed() < 1000)
110             {
111                 splash->raise();
112                 QApplication::processEvents(); //to let the system breath!
113             }
114
115             splash->close();
116             QApplication::processEvents();
117
118             delete splash;
119             splash = 0;
120         }
121
122         //let's rock!
123         try
124         {
125             result = app.exec();
126         }
127         catch(...)
128         {
129             QMessageBox::warning(0, "CC crashed!","Hum, it seems that CC has crashed... Sorry about that :)");
130         }
131     }
132
133     //release global structures
134     MainWindow::DestroyInstance();
135     FileIOFilter::UnregisterAll();
136
137 #ifdef CC_TRACK_ALIVE_SHARED_OBJECTS
138     //for debug purposes
139     unsigned alive = CCShareable::GetAliveCount();
140     if (alive > 1)
141     {
142         printf("Error: some shared objects (%u) have not been released on program end!",alive);
143         system("PAUSE");
144     }
145 #endif
146
147     return result;
148 }

int main(int argc, char **argv)

两处最终都落实到FileIOFilter::SaveToFile()方法的调用。

 1 //保存文件
 2 CC_FILE_ERROR FileIOFilter::SaveToFile(    ccHObject* entities,
 3                                         const QString& filename,
 4                                         SaveParameters& parameters,
 5                                         QString fileFilter)
 6 {
 7     if (fileFilter.isEmpty())
 8         return CC_FERR_BAD_ARGUMENT;
 9     //获取对应的文件格式,存储器
10     Shared filter = GetFilter(fileFilter,false);
11     if (!filter)
12     {
13         ccLog::Error(QString("[Load] Internal error: no filter corresponds to filter '%1'").arg(fileFilter));
14         return CC_FERR_UNKNOWN_FILE;
15     }
16
17     return SaveToFile(entities, filename, parameters, filter);
18 }
19
20 CC_FILE_ERROR FileIOFilter::SaveToFile(    ccHObject* entities,
21                                         const QString& filename,
22                                         SaveParameters& parameters,
23                                         Shared filter)
24 {
25     if (!entities || filename.isEmpty() || !filter)
26         return CC_FERR_BAD_ARGUMENT;
27
28     //if the file name has no extension, we had a default one!
29     QString completeFileName(filename);
30     if (QFileInfo(filename).suffix().isEmpty())
31         completeFileName += QString(".%1").arg(filter->getDefaultExtension());
32
33     CC_FILE_ERROR result = CC_FERR_NO_ERROR;
34     try
35     {
36         result = filter->saveToFile(entities, completeFileName, parameters);
37     }
38     catch(...)
39     {
40         ccLog::Warning(QString("[I/O] CC has caught an unhandled exception while saving file '%1'").arg(filename));
41         result = CC_FERR_CONSOLE_ERROR;
42     }
43
44     if (result == CC_FERR_NO_ERROR)
45     {
46         ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename));
47     }
48     else
49     {
50         DisplayErrorMessage(result,"saving",filename);
51     }
52
53     return result;
54 }

FileIOFilter::SaveToFile

获取需要的文件存储器。

 1 //获取存取器
 2 FileIOFilter::Shared FileIOFilter::GetFilter(QString fileFilter, bool onImport)
 3 {
 4     if (!fileFilter.isEmpty())
 5     {
 6         for (FilterContainer::const_iterator it=s_ioFilters.begin(); it!=s_ioFilters.end(); ++it)
 7         {
 8             QStringList otherFilters = (*it)->getFileFilters(onImport);
 9             if (otherFilters.contains(fileFilter))
10                 return *it;
11         }
12     }
13
14     return Shared(0);
15 }

FileIOFilter::Shared FileIOFilter::GetFilter

这里重点研究一下obj文件的保存。

[CC]Mesh文件保存相关推荐

  1. Unity3d 提取mesh并保存成asset文件

    Unity3d 提取mesh并保存成asset文件 应用背景 下载链接 使用步骤 贴出脚本 应用背景 有些FBX文件过大,但是只用其中的一个mesh时,我们可以考虑把这个mesh单独提取出来保存问as ...

  2. pandas parquet文件读取pyarrow、feather文件保存与读取;requests 或wget下载图片文件

    **pandas读取文件填写绝对路径,相对路径可能出错读不了 安装 fastparquet库,需要安装python-snappy ,一直安装错误,所以使用了pyarrow pip install py ...

  3. PHP ajax 远程下载PDF文件保存在本地服务器

    在一些时候我们想ajax方式来保存一些PDF文件,尤其是它放在远程服务器上,并且是保存在我们自己的服务器上存储,这个时候我们需要写一段程序来帮助我们完成这个工作,本文介绍了PHP 远程下载PDF文件保 ...

  4. Word 2003文件保存和另存为操作是否熟练掌握的有关测试

    提出问题 本文内容不仅适用于Word,对于其他的文档(文字.图形.动画.声音等)编辑软件基本通用. 对于操作上述各种编辑软件时,大家都应该注意到,我们第一次保存文件时系统出现的是"另存为&q ...

  5. R语言write.xlsx函数将数据写入Excel文件:写入Excel文件并自定义表单的名称、将数据写入Excel文件新的表单(sheet)中、将文件保存为xls文件格式(而不是xlsx)

    R语言write.xlsx函数将数据写入Excel文件:写入Excel文件并自定义表单的名称.将数据写入Excel文件新的表单(sheet)中.将文件保存为xls文件格式(而不是xlsx) 目录

  6. C#代码实现把网页文件保存为mht文件

    MHT叫"web单一文件".顾名思义,就是把网页中包含得图片,CSS文件以及HTML文件全部放到一个MHT文件里面.而且浏览器可以直接读取得. 由于项目需要,需实现把指定的网页文件 ...

  7. C# 文件保存到数据库中或者从数据库中读取文件

    首先,介绍一下保存文件到数据库中. 将文件保存到数据库中,实际上是将文件转换成二进制流后,将二进制流保存到数据库相应的字段中.在SQL Server中该字段的数据类型是Image,在Access中该字 ...

  8. REST接口GET方法获取文件保存到本地(C#)

    REST接口GET方法获取文件保存到本地(C#) using System; using System.Collections.Generic; using System.Linq; using Sy ...

  9. 关于文件保存/关闭时报错:文件正由另一进程使用,因此该进程无法访问此文件。...

    起因:最近给Unity上的游戏写关于存档的脚本,使用了xml.然后发现每次文件保存时,也就是调用XmlDocument.Save()对象方法的时候就会报错说该文件路径分享异常啥的我也不记得了.然后搞了 ...

最新文章

  1. Laravel安装后没有vendor文件夹
  2. Deno 并不是下一代 Node.js
  3. 文本编辑器创建状态栏
  4. 吐槽net下没有靠谱的FastDFS的sdk之使用thrift实现JAVA和C#互通
  5. android常见面试问题
  6. 螺丝刀还能悬浮起来?
  7. keychain 的学习
  8. 股票历史数据-股票历史数据查询
  9. 如何从0到1设计业务系统
  10. 纪念杰克韦尔奇:职业经理人怎么做变革
  11. Echarts绘制不均匀数据轴(y)
  12. [分享] 给铭文商人一个草药→草渣→墨水的列表[希望大家有用]
  13. Apple Pencil的平替能用吗?平板绘画笔推荐
  14. docker基本用法
  15. API战略中台的正确落地方式:构建高效的“API管理平台”
  16. nacos+dubbo调用成功案例
  17. Linux运行时IO设备电源管理框架---PM
  18. 特别奔溃---centos7IP自动改变问题
  19. 临床专业有计算机课吗,2021热门专业排行公布,医学专业不再受欢迎,计算机专业稳定...
  20. Hadoop和大数据最炫目的60款顶级开源工具

热门文章

  1. 类脑计算将何去何从?
  2. 绘声绘影给视频加多个马赛克和动态马赛克方法
  3. 高考415分能上计算机网络的学校吗,2021年高考理科415分能上什么学校 理科415分左右的大学有哪些...
  4. 化学品防爆柜怎么接地
  5. 电脑上永久删除的文件怎么恢复?其实很简单
  6. 陪玩app源码,陪玩系统开发约单下单逻辑处理规则
  7. 2018/12/22 一位前端实习生 艰辛过程 励志 实习周记(一)—— 前言
  8. 2016河北省职称计算机考试试题,2016年最新河北省职称计算机考试试题及答案(参考).doc...
  9. vue element datepicker八小时时间差
  10. jda是oracle,jda软件品类管理解决方案.ppt