Страницы

Поиск по вопросам

четверг, 31 января 2019 г.

Как получить местное время из серверного?

На локальной машине функция DateTime.Now.ToString() дает результат
27.06.2016 15:27:55
, а при развертывании на сервер
6/28/2016 1:14:55 AM
Как привести второй вариант в первому? Желательно без разбора строк.


Ответ

DateTime.Now.ToString(CultureInfo.GetCultureInfo("ru-ru"))
Класс CultureInfo находится в пространстве имен System.Globalization
Если получение строкового представления даты вызывается многократно в разных местах, и каждый раз явно указывать язык неудобно, то можно установить локаль в рамках всего треда:
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("ru-ru");

Если сервер находится в другом часовом поясе, а дату нужно получить, например, по московскому времени, то воспользуйтесь классом TimeZoneInfo
static string GetCurrentDateTime() { var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"); return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz) .ToString(CultureInfo.GetCultureInfo("ru-ru")); }
Список идентификаторов часовых поясов можно получить, вызвав TimeZoneInfo.GetSystemTimeZones()

Как вставить текст в скрытый textarea с помощью selenium webdriver

День добрый. Каким образом можно вставить текст в скрытый элемент Textarea с помощью Selenium Webdriver


Ответ

Dim txtScript = String.Format("arguments[0].innerText = '{0}';", "texttexttext") DirectCast(driver, IJavaScriptExecutor).ExecuteScript(txtScript, element)

Почему файл не добавляется в .gitignore? [дубликат]

На данный вопрос уже ответили: Не игнорируются файлы в .gitignore 2 ответа Я составил .gitignore файл положил его в корень проекта в файле есть указание на то что нужно игнорировать файлы типа .idea/workspace.xml
# Intellij *.iml .idea/workspace.xml .idea/libraries
Но все равно когда пишу git status получаю
Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory)
modified: .idea/workspace.xml
Что делаю не так?


Ответ

Строка
modified: .idea/workspace.xml
говорит что офайл уже в индексе, это значит что его для начала нужно перестать отслеживать
git rm --cached .idea/workspace.xml
GIT rm
после этого если файл правильно добавлен в gitignore то при команде
git status
файла не доолжно быть
Добавление gitignore
git add .gitignore git commit -m"gitignore was updated" gut push origin master

Не выводит случайное число в PHP

В чем разница volatile и static?

Если я правильно понял, то static хранит только последнее записанное в него значение, без разницы сколько потоков обращаются к этой переменной, каждый кто обратиться к ней получит последнее записанное значение.
А volatile в свою очередь создается с новым созданным объектом и при обращении к ней из разных потоков он возвращает самое свежее значение своего объекта.
Запутанно объяснил наверное, но вот как то так я понял...
Не знаю насколько принципиальная разница...


Ответ

volatile означает, что чтение и запись переменной с данным квалификатором является атомарной операцией, при этом любое изменение такой переменной будет видно из других потоков.
static никак не связано с многопоточностью, этот модификатор указывает, что переменная не принадлежит объекту, она ассоциирована с классом/интерфейсом. Операции над static-переменными не являются потокобезопасными. При этом каждый поток может работать со своей копией статической переменной (если она не объявлена как volatile) - соответственно без синхронизации изменения в такую переменную могут быть не видны другим потокам.

Java Memory Model и happens-before

Добрый день. Есть небольшой вопрос по JMM. Я знаю как работает happens-before, но не могу понять один момент. Вот код:
private static int x = 0; private static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> { x = 10; while (!flag) ; System.out.println(x); }).start();
x = 5; flag = true; }
Какое значение должно принять X? Если какое-то правило чтобы определить это?


Ответ

Если изобразить потоки выполнения в вашем коде, мы получим такую картину:

Main thread - это основной поток вашей программы, Thread1 - поток, который вы явно создаете.
Запись и чтение волатильной переменной flag действительно создают отношение Happens-Before (E → B на диаграмме). Таким образом по отношению к вызову System.out.println(x); у нас есть два потока выполнения, для каждого из которых гарантируется порядок выполнения: A → B → C и D → E → B → C. Запись в переменную x произойдет гарантированно раньше ее чтения.
Но вот инструкции записи в переменную x (A и D) находятся в состоянии гонки (race condition) и их порядок выполнения друг относительно друга не определен. В итоге то, что мы видим на диаграмме никак нельзя назвать полным порядком. JVM вполне может выполнить инструкции следующим образом:

Вопрос касательно методов Ruby

В чем разница между методами map и collect?
Подскажите плиз когда использовать map, а когда collect?


Ответ

Абсолютно никакой разницы.
Исходники этих методов указывают в один и тот же код на Си. (для массивов они реализованы на Си отдельно, но тоже одинаково)
Проверьте сами, установив и запустив pry и сделав на интересующем объекте obj
show-source obj.collect show-source obj.map

Что использовать — холивар
Есть лица, считающие, что надо использовать их так, чтобы код хорошо читался. В этом контексте обычно лучше работает collect (собрать), как "собрать результаты выполнения блока для каждого элемента". Есть лица, считающие, что надо всегда использовать map, потому что это широко известная (вне Ruby) операция преобразования данных, в которой каждый элемент коллекции преобразуется независимо от остальных. Есть лица, жалеющие, что в Ruby так много синонимов и потому так много споров о чисто косметических вещах (bikeshedding).
collect_concat vs. flat_map reduce vs. inject detect vs. find find_all vs. select include? vs. member?

Как увеличивать значение style.left?

function right() { square.style.left += 50+'px'; }
Как устанавливать не фиксированное значение в style.left, а прибавлять\отнимать его ?


Ответ

Данное свойство является строкой, поэтому прежде чем увеличивать его, его надо перевести в число, например используя функцию parseInt
function right() { square.style.left = (parseInt(square.style.left,10)+50)+'px'; }
Пример:
var square = document.getElementById('square'); square.onclick = function() { right() } function right() { square.style.left = (parseInt(square.style.left, 10) + 50) + 'px'; } #square { position: absolute; background-color: lime; width: 40px; height: 40px; }


Стоит обратить внимание на то, что свойство left установлено в inline стилях, в противном случае оно будет равно пустой строке, и parseInt(square.style.left, 10) вернет NaN
Другим вариантом, может быть использование функции getComputedStyle, позволяющей получить текущее значение свойства, как значения по умолчанию, в случае, когда inline свойство пустое.
var square = document.getElementById('square'); square.onclick = function() { right() } function right() { square.style.left = (parseInt(square.style.left || getComputedStyle(square)['left'], 10) + 50) + 'px'; } #square { position: absolute; background-color: lime; width: 40px; height: 40px; }

Visual Studio. Отсутствует меню создания ASP.NET проекта

При попытке создания проекта ASP.NET в Visual Studio в пути
ФАЙЛ > Создать > Проект > Веб
отсутствует меню создания проектов ASP.NET. На его месте находится элемент WebTemplate. При создания проекта данного типа (WebTemplate), Visual Studio выдаёт ошибку.
Как должно выглядеть:

Как это у меня выглядит:

Версия Visual Studio Enterprise 2015 Update 3. Web компоненты присутствуют. Пробовал делать Repair (так как Repair от онлайн установщика Visual Studio 2015 Update 3 был недоступен, я использовал версии Update 0).


Ответ

Переустановка Visual Studio помогла решить данную проблему. После удаления, я удалил все директории принадлежащие Visual Studio
Такие как:
C:\Program Files (x86)\Microsoft Visual Studio 11.0 C:\Program Files (x86)\Microsoft Visual Studio 12.0 C:\Program Files (x86)\Microsoft Visual Studio 14.0
Очистил реестр от нерабочих значений, прочистил жесткий диск на файлы .tmp, .old и так далее при помощи утилиты WinTools.net.
На место старой Visual Studio 2015 Update 3 начал установку Visual Studio 2015 [без обновлений], к счастью, установщик сам установил необходимые компоненты и обновления. Сейчас сижу на Visual Studio 2015 Update 3

Арифметика с плавающей точкой

Возникла необходимость перевести секунды в милисекунды. Скрипт:
#!/bin/bash a=$(ffprobe -i c848a39afc54e04cc64ddd955686654b9b1c6f31 -show_entries format=duration -v quiet -of csv="p=0"); b=1000; result=$(($a*$b)); echo $result
Вывод
./sectomilisec: line 4: 23.760000*1000: syntax error: invalid arithmetic operator (error token is ".760000*1000")
Как правильно умножить вывод операции на число?


Ответ

invalid arithmetic operator (error token is ".760000*1000")
в программе bash не реализована арифметика с плавающей точкой (только целочисленная).
для осуществления таких вычислений придётся воспользоваться какой-то другой программой. например, bc
result=$(echo "$a*$b" | bc -l)
или dc
result=$(echo "$a $b + p" | dc)

подробности:
bc: википедия, man bc, info bc dc: википедия, man dc, info dc

кстати, в этом выражении знаки доллара перед именами переменных не нужны:
result=$(($a*$b))
достаточно (и более правильно) так:
result=$((a*b))

Как отличить событие закрытия Activity от поворота экрана?

Как программно отличить событие настоящего закрытия Activity от промежуточных вызовов onStop() и onDestroy() при повороте экрана (изменения ориентации экрана)?


Ответ

Метод boolean isFinishing(). Вызывается обычно в onPause()

Зачем нужны абстрактные классы коллекций помимо интерфейсов?

Почему в Java, кроме интерфейсов коллекций, есть соответствующие им абстрактные классы. Например, есть интерфейс Collection. и абстрактный класс AbstractCollection, List и AbstractList. Почему недостаточно только интерфейса?


Ответ

Абстрактные классы - это helper-классы, предоставляющие базовую умолчательную "скелетную" реализацию функциональности соответствующих интерфейсов. Например, класс AbstractCollection предоставляет пользователю "скелетную" реализацию интерфейса Collection. Для того, чтобы реализовать свою коллекцию, вам нужно просто унаследоваться от AbstractCollection и предоставить свои собственные реализации тех методов, которые специфичны для вашей коллекции. А те, которые неспецифичны - просто унаследуются в готовом виде из AbstractCollection. Таким образом вам не нужно будет писать ворох "скучных" методов с тривиальной или рутинной реализацией.
В то же время вы не обязаны пользоваться AbstractCollection. Вы имеете полное право, если вам так захочется, реализовать интерфейс Collectionсвоими силами, с нуля, не пользуясь услугами AbstractCollection
Точно также проведено разделение между List и AbstractList

Внутренний vs Анонимный vs Отдельный классы

В ходе изучения языка все реже возникают вопросы "Как решить задачу?" и все чаще встает вопрос "Какой способ более правильный с точки зрения хорошего тона программирования?"
К примеру, в ходе написания программы, реализующей возможность ведения складского учета, возник вопрос, какой класс использовать: анонимный, внешний или внутренний? Есть класс главного окна программы, реализующий JDesktopPane. Есть отдельный класс "Каталог товаров", реализующий JInternalFrame. Из последнего, нажатием кнопок, открывается окно Карточки товара" (также класс extends JInternalFrame). В свою очередь кликом по кнопкам он реализует открытие окон выбора группы товара, единицы измерения, категории и т.д. Все это тоже JInternalFrame
Вот теперь стоит вопрос, какой тип класса "эстетичнее" использовать? Логика подсказывает делать все классы ниже "Каталога товаров" вложенными в него, а все слушатели нажатия кнопок - анонимными. Но тогда класс получается под тысячу строк кода, что влияет на читаемость. Или это нормально? В общем я как тот осел, между двумя стогами сена.
Вот, к примеру, такой участок кода. Оптимален ли он, или стоит изменить структуру?
package catalogs; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.beans.PropertyVetoException; import java.io.File; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ListSelectionModel; import javax.swing.event.TableModelListener; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.table.TableModel; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import main.Global;
/** * Класс окна справочника товара. Выводит окно каталога товаров с возможностью добавления/удаления/редактирования групп товаров и самих * товаров. Представляет собой древо групп товаров, таблицу товаров, кнопки добавления/удаления/редактирования. */
public class ProductCatalog extends JInternalFrame{ private static final long serialVersionUID = 1L;
private JDesktopPane mainPane; public JTree treeGroup; private GroupTreeModel treeGroupModel; private JScrollPane treeGroupScrlPane; private JButton btnAddGroup; private JButton btnDelGroup; private JButton btnEditGroup; public JTable tblProduct; public ProdTableModel tblProductModel; private JScrollPane tblProductScrlPane; private JButton btnAddProduct; private JButton btnDelProduct; private JButton btnEditProduct;
/** * Конструктор, принимает ссылку на JDesctopPane главного окна. */ public ProductCatalog(JDesktopPane mainPane){ this.mainPane = mainPane; paintComponents(); }
/** * Метод отрисовки компонент окна. */ private void paintComponents(){ treeGroupModel = new GroupTreeModel(); treeGroup = new JTree(treeGroupModel); treeGroup.setSelectionRow(0); treeGroup.addTreeSelectionListener(new TreeSelectionListener(){ @Override public void valueChanged(TreeSelectionEvent selection) { if(!treeGroup.isSelectionEmpty()){ tblProductModel.buildTable(treeGroup.getLastSelectedPathComponent()); tblProduct.revalidate(); tblProduct.repaint(); } } }); treeGroupScrlPane = new JScrollPane(treeGroup); treeGroupScrlPane.setBounds(10, 10, 150, 260);
btnAddGroup = new JButton(); ImageIcon btnAddGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnAddGroup.png"); btnAddGroup.setIcon(btnAddGroupIcon); btnAddGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { addGroup(); } }); btnAddGroup.setBounds(10, 280, 30, 30); btnDelGroup = new JButton(); ImageIcon btnDelGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnDelGroup.png"); btnDelGroup.setIcon(btnDelGroupIcon); btnDelGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { delGroup(); } }); btnDelGroup.setBounds(50, 280, 30, 30); btnEditGroup = new JButton(); ImageIcon btnEditGroupIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnEditGroup.png"); btnEditGroup.setIcon(btnEditGroupIcon); btnEditGroup.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { editGroup(); } }); btnEditGroup.setBounds(90, 280, 30, 30);
tblProductModel = new ProdTableModel(); tblProduct = new JTable(tblProductModel); tblProductModel.buildTable(treeGroup.getLastSelectedPathComponent()); tblProduct.setAutoCreateRowSorter(true); tblProduct.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); tblProduct.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tblProduct.getColumnModel().getColumn(0).setPreferredWidth(25); tblProduct.getColumnModel().getColumn(1).setPreferredWidth(200); tblProduct.getColumnModel().getColumn(2).setPreferredWidth(25); tblProduct.getColumnModel().getColumn(3).setPreferredWidth(50); tblProductScrlPane = new JScrollPane(tblProduct); tblProductScrlPane.setBounds(170, 10, 500, 260);
btnAddProduct = new JButton(); ImageIcon btnAddProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnAddProduct.png"); btnAddProduct.setIcon(btnAddProductIcon); btnAddProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { addProduct(); } }); btnAddProduct.setBounds(170, 280, 30, 30); btnDelProduct = new JButton(); ImageIcon btnDelProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnDelProduct.png"); btnDelProduct.setIcon(btnDelProductIcon); btnDelProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { delProduct(); } }); btnDelProduct.setBounds(210, 280, 30, 30); btnEditProduct = new JButton(); ImageIcon btnEditProductIcon = new ImageIcon(Global.getAppPath()+File.separator+"images"+File.separator+"btnEditProduct.png"); btnEditProduct.setIcon(btnEditProductIcon); btnEditProduct.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { editProduct(); } }); btnEditProduct.setBounds(250, 280, 30, 30);
this.setTitle("Каталог товаров"); this.addComponentListener(new ComponentListener(){ @Override public void componentResized(ComponentEvent e) { treeGroupScrlPane.setBounds(10, 10, 150, ProductCatalog.this.getHeight()-87); btnAddGroup.setBounds(10, ProductCatalog.this.getHeight()-67, 30, 30); btnDelGroup.setBounds(50, ProductCatalog.this.getHeight()-67, 30, 30); btnEditGroup.setBounds(90, ProductCatalog.this.getHeight()-67, 30, 30); tblProductScrlPane.setBounds(170, 10, ProductCatalog.this.getWidth()-200, ProductCatalog.this.getHeight()-87); btnAddProduct.setBounds(170, ProductCatalog.this.getHeight()-67, 30, 30); btnDelProduct.setBounds(210, ProductCatalog.this.getHeight()-67, 30, 30); btnEditProduct.setBounds(250, ProductCatalog.this.getHeight()-67, 30, 30); } @Override public void componentHidden(ComponentEvent arg0) {} @Override public void componentMoved(ComponentEvent arg0) {} @Override public void componentShown(ComponentEvent arg0) {} }); this.setClosable(true); this.setMaximizable(true); this.setIconifiable(true); this.setResizable(true); this.getContentPane().setLayout(null); this.setSize(700, 347); this.setVisible(true); this.add(treeGroupScrlPane); this.add(btnAddGroup); this.add(btnDelGroup); this.add(btnEditGroup); this.add(tblProductScrlPane); this.add(btnAddProduct); this.add(btnDelProduct); this.add(btnEditProduct); }
/** * Рекурсивный метод построения массива элементов древа групп товаров. */ ArrayList arr = new ArrayList(); public ArrayList getComboBoxTree(Object parent, String separator){ Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+parent+"'"); for(int i=0; i0) getComboBoxTree(buf[i][0], " "+separator); } return arr; }
/** * Метод, реализующий добавление группы товаров в БД. */ private void addGroup(){ String name = JOptionPane.showInputDialog(null, "Введите название новой подгруппы
в группе \""+ treeGroup.getLastSelectedPathComponent() +"\":", ""); if(name!=null){ Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ name +"'"); if(buf.length==0){ if(name.length()>0){ Object[][] parentGroup = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); Global.sqlQueryVoid("INSERT INTO `prod_group` (`name`, `parent`) VALUES ('"+ name +"', '"+ parentGroup[0][0] +"')"); treeGroup.updateUI(); }else JOptionPane.showMessageDialog(null, "Наименование группы товаров не может быть пустым!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }else JOptionPane.showMessageDialog(null, "Группа товаров с таким наименованием уже существует!", "Ошибка!", JOptionPane.ERROR_MESSAGE); } }
/** * Метод, реализующий удаление группы товаров из БД. */ private void delGroup(){ boolean isEmpty = false; Object[][] buf = Global.sqlQueryResult("SELECT `id` FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); Object[][] buf2 = Global.sqlQueryResult("SELECT * FROM `product` WHERE `group`='"+ buf[0][0] +"'"); Object[][] buf3 = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ buf[0][0] +"'"); if(buf2.length==0 && buf3.length==0) isEmpty = true; if(!treeGroup.getLastSelectedPathComponent().equals(null)){ //Если выделена группа, if(isEmpty){ //она пуста if(JOptionPane.showConfirmDialog(null, "Вы уверены?", "Подтверждение удаления", JOptionPane.YES_NO_OPTION)==0){ //и мы подтверждаем удаление, тогда удаляем. Global.sqlQueryVoid("DELETE FROM `prod_group` WHERE `name`='"+ treeGroup.getLastSelectedPathComponent() +"'"); treeGroup.updateUI(); } }else JOptionPane.showMessageDialog(null, "Нельзя удалить эту папку, т.к. она не пуста!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }else JOptionPane.showMessageDialog(null, "Вы не выбрали ни одну папку!", "Ошибка!", JOptionPane.ERROR_MESSAGE); }
/** * Метод, реализующий редактирование группы товаров в БД. */ private void editGroup(){
if(treeGroup.getSelectionRows()[0] != 0){ //Если выбрана не корневая группа, переименовываем группу товаров. final JInternalFrame ifEditGroup; final JComboBox cbParent; final JLabel lblName; final JTextField tfName; final JButton btnOK; final JButton btnCancel; final ArrayList arr;
ifEditGroup = new JInternalFrame();
JLabel lblParent = new JLabel("Родительская группа:"); lblParent.setBounds(10, 10, 150, 20); cbParent = new JComboBox(); cbParent.setBounds(170, 10, 250, 20); arr = getComboBoxTree(0, ""); for(int i=0; i ifEditGroup.getContentPane().setLayout(null); ifEditGroup.add(lblParent); ifEditGroup.add(cbParent); ifEditGroup.add(lblName); ifEditGroup.add(tfName); ifEditGroup.add(btnOK); ifEditGroup.add(btnCancel); ifEditGroup.setTitle("Редактирование группы товаров"); ifEditGroup.setSize(450, 130); ifEditGroup.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); ifEditGroup.setVisible(true);
boolean isOpened = false; Object[] ifArr = mainPane.getAllFrames(); for(int i=0; i/** * Метод, реализующий добавление товара в БД. */ private void addProduct(){ boolean isOpened = false; Object[] ifArr = mainPane.getAllFrames(); for(int i=0; i/** * Метод, реализующий удаление товара из БД. */ private void delProduct(){ if(JOptionPane.showConfirmDialog(null, "Вы уверены?", "Подтверждение удаления", JOptionPane.YES_NO_OPTION)==0){ String code = ProductCatalog.this.tblProduct.getValueAt(ProductCatalog.this.tblProduct.getSelectedRow(), 0).toString(); Global.sqlQueryVoid("DELETE FROM `product` WHERE `id`='"+code+"'"); Global.sqlQueryVoid("DELETE FROM `prod_barcode` WHERE `prod_id`='"+code+"'"); ProductCatalog.this.tblProductModel.buildTable(ProductCatalog.this.treeGroup.getLastSelectedPathComponent()); ProductCatalog.this.tblProduct.revalidate(); ProductCatalog.this.repaint(); } }
/** * Метод, реализующий редактирование товара в БД. */ private void editProduct(){ boolean isOpened = false; Object[] arr = mainPane.getAllFrames(); for(int i=0; i/** * Модель дерева. */ private class GroupTreeModel implements TreeModel{ @Override public Object getChild(Object parent, int index) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); return res[index][1]; } @Override public int getChildCount(Object parent) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); return res.length; } @Override public int getIndexOfChild(Object parent, Object child) { Object[][] buf = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `name`='"+ parent +"'"); Object parentCode = buf[0][0]; Object[][] res = Global.sqlQueryResult("SELECT * FROM `prod_group` WHERE `parent`='"+ parentCode +"'"); int index = 0; for(int i =0; i /** * Модель таблицы. */ public class ProdTableModel implements TableModel{ private Object[][] sample = null;
public void buildTable(Object group){ //Метод построения двумерного массива данных, на основе которого отрисовывается таблица товаров. Object[][] buf = Global.sqlQueryResult("SELECT `id` FROM `prod_group` WHERE `name`='"+ group +"'"); sample = Global.sqlQueryResult("SELECT `product`.`id`, `product`.`name`, `prod_unit`.`short_name`, `product`.`comments` " + "FROM `product` LEFT JOIN `prod_unit` ON `product`.`unit`=`prod_unit`.`id`" + " WHERE `product`.`group`='"+ buf[0][0] +"'"); } @Override public Class getColumnClass(int colInd) { return String.class; } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int colInd) { String colName =""; switch(colInd){ case 0: colName = "Код"; break; case 1: colName = "Наименование"; break; case 2: colName = "Ед. изм."; break; case 3: colName = "Комментарий"; break; } return colName; } @Override public int getRowCount() { return sample.length; } @Override public Object getValueAt(int rowInd, int colInd) { return sample[rowInd][colInd]; } @Override public void addTableModelListener(TableModelListener arg0) {} @Override public boolean isCellEditable(int arg0, int arg1) {return false;} @Override public void removeTableModelListener(TableModelListener arg0) {} @Override public void setValueAt(Object arg0, int arg1, int arg2) {} } }


Ответ

Анонимные классы удобны там, где цель существования типа - применение в одной единственной точке на всё приложение. Внутренний (нестатический) класс существует внутри внешнего и может быть там скрыт. Кроме того сам имеет доступ к скрытому состоянию родителя.
Если такие "суперспособности" не принесут ощутимой пользы, то стоит склоняться к отдельным классам.
Отдельные классы читаются лучше (и соответствуют Single responsibility) при прочих равных.
А вообще, это достаточно тонкая грань между хорошим кодом и плохим. Чувство прекрасного развивается при чтении чужого кода, где ты распутывая клубок алгоритма подмечаешь для себя какие-то элегантные решения и злишься на излишнюю запутанность других.

Алгоритм определения коллизии цилиндра и сложного тела

Дано:
1) Сложное тело (меш ландшафта), состоящее из треугольных полигонов
2) Простое тело (к примеру цилиндр). Для него известна точка центра и все его измерения.
Нужен алгоритм определения наличия пересечения этих двух тел. При этом, сложное тело много больше простого (по размерам и количеству вершин).
Основная задача - как можно быстрее ответить, есть ли пересечение между этими телами. Допускается предобработка сложного тела.
Какие вообще есть подходы для решения подобной задачи?

Так же скажу сразу, что нужен именно алгоритм, а не какой-то физический движок, который все это сам определит.


Ответ

Разбить поиск на этапы. Первый это грубое отсечение, по крайним координатам тел. Если коллизия не найдена, значит тела не пересекаются. Если найдена, тогда преступаем к детальному отсечению по полигонам попавшим в эту область.
Можете почитать более детально про алгоритмы Sweep And Prune и V-Clip

Проблема с настройкой меню bootstrap'а

Здравствуйте. Подскажите пожалуйста такую вещь. Я создал меню через bootstrap, прописал стили. Но когда я начал уменьшать размер меню, то он стал "съедать буквы". Нужно как-то поднять их. Спасибо.
.navbar-collapse { background: linear-gradient(to top, #4c4e5a 0%, #2c2d33 100%); border-radius: 5px; } .navbar-nav>li>a { color: white; } .navbar-nav>li>a:hover { color: #FF6600; height: 36px } .navbar-nav>li { border-right: 1px solid gray; height: 100%; } .nav { height:30px; font-size: 18px; } Zont-SPB

E-mail:

Телефон:



Ответ

Высота навбара в бутстрапе влияет не только на .navbar { height: xxx; }, но и на свойства других компонентов, например отступов у ссылок .navbar .nav > li > a { padding: xxx; }
Исходники бутстрапа написаны в LESS (SASS в четвертой версии), оба препроцессора позволяют использовать переменные для кастомизации стилей. На высоту навбара влияет переменная $navbar-height
Так как вы не используете LESS/SASS-версию бутстрапа, возможности повлиять на высоту навбара у вас две:
Перейти на http://getbootstrap.com/customize/, поменять значение @navbar-height и собрать себе уникальный css-файл, и подключить уже его, вместо https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css Открыть исходники бутсрапа и найти все места, где фигурирует переменная $navbar-height, пересчитать значения свойств во всех этих местах и разместить стили у себя, они применятся поверх стандартных бутстраповских